I'm extensively using groovy classes in my web app project. I can create an instance of a type (defined as a groovy class) but can never at a later time cast back to it (GroovyCastException occurs).
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.company.role.delegation.ProfileModel#49ee6848' with class 'com.company.role.delegation.ProfileModel' to class 'com.company.role.delegation.ProfileModel'
According to the above error message, the source and destination class types are the same. Huh?
Most likely the reason is that the class have been loaded twice via different classloaders. Check if the getClass().getClassLoader() for both the instances are identical.
Related
In a java program, when a class is loaded into the method area the Class type object is created in the heap area. Questions:
If 10 .class files are loaded then 10 Class type objects are created right?
What is the purpose of creating the Class type object for every .class file by JVM?
There are probably many many reasons. Like: you want to write code such as:
Class<Foo> fooClass = Foo.class;
Annotation[] annotations = fooClass.getAnnotations();
Meaning: the class Class enables you to programmatically inspect (reflect) on your types. Or to use reflection to invoke constructors or methods based on raw strings.
And of course: the JVM itself needs all kinds of information about the classes it knows. So it makes perfect sense to "collect" all that information right at the point when the class is loaded.
Imagine you are a shop owner, and you decide to carry a new item. One of the things to do: update your internal inventory that lists all items, and maybe describes the attributes/properties that matter to you.
After loading a .class file, JVM will create an object of the type java.lang.Class in the Heap area. We can use this class object to get Class level information. It is widely used in Reflection.
Source : https://www.geeksforgeeks.org/object-class-in-java/
I believe this part is handled by JVM's ClassLoader system.
Except the first class of main(), ClassLoader system creates class type objects statically if new is triggered or dynamically if Class.forName() is used. In Object oriented concept class type object is reference to the class.
I was using Google Dataflow and have encountered an error of
java.lang.IllegalArgumentException: unable to serialize ...
from SerializableUtils.class even I have serialVersionUID defined. I suspected the reason could be that I import non standard java library which is not listed on JRE Class While List . In my case I import javassist. I just want to confirm this is case.
it turns out that whether or not the imported third party library is on the JRE Class While List has nothing to do with this error. Dataflow runs on compute engine which is not restricted to the app engine white list. The culprit to my error is due to the introduction of a class member which is not serializable even though the the class itself implements Serializable interface.
Serialization is about the fields in your classes - as this is the process of turning an existing Java object into a sequence of bytes; based on the content of that object.
An import within your Java source code is just a hint for the compiler to understand where names are coming from.
In other words: importing class A within source code for class B doesn't necessarily mean that class A will be serialized. You need to have a field of type A within B for that part!
I need to have an app that during run-time can load another class and deserialize one of it's instance successfuly so that it can run it's methods and read the member variables.
From what I noticed, you can not serialize methods in Java, so I'm thinking about serializing the class instance in project2, load the compiled class with ClassLoader in project1, instantiate it and assign the deserialized instance from porject2 in project1 to the instantiated loaded class.
The serialized class will inherit the same parent class in both projects.
Is this the best way to go? It's a school project so the requirements are that my app can accept any other type of class without changing the code.
TL;DR: My plan is to load a compiled class with the ClassLoader so that my project knows about that class (specifically the methods inside) and then load that serialized class instance inside the project so that I can get the data from the instance and together with the loaded class (now I know the methods aswell), run the methods on the deserialized instance.
You are mistaken. The ability to call a method on some object isn't related to serialization at all.
What I mean: the method implementation is not part of the serialized data! Java serialization only writes field data into that output stream.
The implementation of a method only depends on the class file of some Java class. You can serialize and deserialize your objects as often as you want to - but what happens when you call a method on such an object is only determined by the class file that the corresponding class loader loaded for you when first accessing the corresponding class.
If your goal is really just about "one class dumps an object into a binary representation"; and another piece of code loads that binary data; turns it into an object; to access that object; then you do not need two projects. You also do not need to worry about "the methods being" there. As long as your ClassLoader knows the class of objects to be de-serialized, everything will just work. Just pick an example tutorial, like this here and work through it.
But: when your requirement is to invoke methods or access fields of arbitrary objects; then you don't look into serialization, but into Java reflection.
But a word of warning there: reflections sounds easy, but be assured: there are many many ways for you to write slightly wrong code. And because reflection is basically a runtime thing, the java compiler doesn't help much. You write code that looks reasonable, it compiles, you run it, and you get exceptions throw at you.
In that sense, reflection is an advanced topic in the Java curriculum; and I think you should rather step back and clarify with your teachers what exactly they expect from you.
Given your latest updates: then simply look into that tutorial about serialization (and forget about the reflection part). And to answer your question: yes, that sounds like a viable approach. Can't say more; as you are not sharing code so far.
I am writing code that adds functions to a 'mod' if it exists in the classpath (referenced by pixelmonPresent)
PixelHammerTool extends ItemHammer
, ItemHammer only exists if pixelmon is present
The issue im having is, if i do this in the class (same package)
if(Basemod.pixelmonPresent) {
rubyHammer = new PixelHammerTool(Basemod.RUBY, "pixelutilitys:RubyHammer", "rubyHammer");
}
It will cause a class not found on PixelHammerTool,
Why is this being called if the if statement is false and what can i do about it ?
The why is simple and straightforward: because when a class is loaded, all the classes referenced by it are loaded too. (In fact they are loaded first.)
Avoiding it isn't too complicated either, although the code won't look nice: you need to load the class with reflection, using Class.forName(), find the constructor you want from the array returned by Class.getConstructors() and then create an instance using Constructor.newInstance().
Note that while if it only happens a few times in your code, this solution is fine, if you find yourself doing this a lot then you should probably look for a dependency injection framework that will do the heavy lifting for you.
Under the Linking section in the specs, we see this:
For example, a Java Virtual Machine implementation may choose to resolve each symbolic reference in a class or interface individually when it is used ("lazy" or "late" resolution), or to resolve them all at once when the class is being verified ("eager" or "static" resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized. Whichever strategy is followed, any error detected during resolution must be thrown at a point in the program that (directly or indirectly) uses a symbolic reference to the class or interface.
So when the constant has to be defined is implementation-dependent, based on the class loader. The behavior you're seeing is consistent with the "eager" resolution mentioned: when you reference PixelHammerTool in your code, even if it's for a runtime path that will never be hit, the class loader tries to link in its definition, which does not exist.
This strategy causes the JVM to start slower but execute faster at runtime, which is generally the strategy taken in all the implementations I'm familiar with. Indeed, the default class loader is given the name "bootstrap class loader" because it has this behavior - load classes at JVM bootstrap time.
You can either instantiate the class via reflection, as biziclop suggested (the easier route), which forces linking at runtime, or find or create a class loader that instantiates classes lazily.
We do have a cache (Map) with objects of Class TestClass. Another classloader initializes/loads TestClass at runtime again, so below code will threw a ClassCastException:
TestClass obj1 = (TestClass)map.get("key"); // throws a ClassCastException
ClassCastException when casting to the same class
Alright, I do understand this issue up to this point.
So, I was trying to find background information why is TestClass.class not equals TestClass.class. I assume that the different classloader set a different id to the ReferenceType? Anyone able to explain the background to me?
Best page I've found:
http://www.objectsource.com/j2eechapters/Ch21-ClassLoaders_and_J2EE.htm
Yes, your research points to the right direction: the same class definition loaded by different class loaders is seen as two distinct classes by the JVM. Thus casting between them fails with ClassCastException.
I think the difference is simply because there are two distinct class token objects in play. It has to be like this, since the classes loaded by the different loaders may in fact be different versions of the same class. It is known that the class token for every class is unique (within the same classloader realm, that is). It would open up a can of worms if the JVM started to compare class tokens by their various attributes, rather than by physical equality (==).
What you experienced is the reason why custom class loaders exist. They allow to load different class with the same name in one JVM. The identity of a class in a JVM is given by the tuple consisting of the class name and the class loader. In the language Java a class is identified just by fully qualified name.
Anyone able to explain the background to me?
As Péter Török already explained they are considered different when loaded from different classloaders.
The background is that an application server should be able to support different versions of an application e.g. different versions of the same libraries included in your ear-files.
There is no mystery. Runtime equality of types is defined in the Java Language Specification as follows:
"At run time, several reference types with the same binary name may be loaded simultaneously by different class loaders. These types may or may not represent the same type declaration. Even if two such types do represent the same type declaration, they are considered distinct."
JLS 4.3.4 - When reference types are the same. (2nd paragraph)