java.lang.IllegalArgumentException: unable to serialize myclass - java

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!

Related

Loading a compiled class in Java and deserializing it's instance from a file

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.

How to resolve IncompatibleClassChangeError interface not implemented

I know the question is asked already but somehow I can't find any convincing solution after googling for about an hour.
I am using apache-jena to load RDF model from a url. And I am getting IncompatibleClassChangeError with following message
Class org.apache.http.impl.client.SystemDefaultHttpClient does not implement the requested interface org.apache.http.client.HttpClient
Can someone give some pointer how can I resolve this error.
Regards
Ahsan
This is thrown when an incompatible class change has occurred to some class definition. The definition of some class, on which the currently executing method depends, has since changed. It is normally thrown when a non-final field of a base class becomes static, or when the base class turns into an interface (and vice versa), etc.
The IncompatibleClassChangeError extends the LinkageError, which is related to problems rising from a base class that changes after the compilation of a child class.
Please read more here
http://examples.javacodegeeks.com/java-basics/exceptions/java-lang-incompatibleclasschangeerror-how-to-resolve-incompatible-class-change-error/
http://howtodoinjava.com/2013/05/25/solved-java-lang-incompatibleclasschangeerror-implementing-class/
Your newly packaged library is not backward binary compatible (BC) with old version. For this reason some of the library clients that are not recompiled may throw the exception.
This is a complete list of changes in Java library API that may cause clients built with an old version of the library to throw java.lang.IncompatibleClassChangeError if they run on a new one (i.e. breaking BC):
Non-final field become static,
Non-constant field become non-static,
Class become interface,
Interface become class,
if you add a new field to class/interface (or add new super-class/super-interface) then a static field from a super-interface of a client class C may hide an added field (with the same name) inherited from the super-class of C (very rare case).
Note: There are many other exceptions caused by other incompatible changes: NoSuchFieldError, NoSuchMethodError, IllegalAccessError, InstantiationError, VerifyError, NoClassDefFoundError and AbstractMethodError.
The better paper about BC is "Evolving Java-based APIs 2: Achieving API Binary Compatibility" written by Jim des Rivières.
There are also a lot of automatic tools to detect such changes:
japi-compliance-checker
clirr
japitools
sigtest
japi-checker
Usage of japi-compliance-checker for your library (*.jar):
japi-compliance-checker OLD.jar NEW.jar
Usage of clirr tool:
java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar

Java ClassCastException with two identical classes in different packages, sent over the network

I'm having following problem: My project consists out of two packages (Client and Server), where each of them has the class Package. Now i want to send this class over the network via ObjectOutputStream / ObjectInputStream like this:
//Client - this is in package client
ObjectOutputStream out = new SocketOutputStream(socket.getOutputStream);
Package package = new Package();
out.writeObject(package);
//Server - this is in package server
ObjectInputStream in = new SocketInputStream(socket.getInputStream);
Object o = in.readObject();
if(o instanceof Package) ... //do something important
So the problem lies in the last line, where I get a ClassCastException. The reason is obviously that he takes full path to determine the type of the object, so client.Package is not server.Package. The Problem is that i cannot put the client package to the server or vice versa.
So here is the real Question: Can i determine the type of the class without importing the Package class from the package (client / server)? Or is there a possibility to send the Object over the network without class information ?
Edit:
The Package class looks as following:
public class Package implements Seriablizable {
private static final long serialVersionUID = 5050301321863757269L;
public String objectName;
public Object[] parameters;
public Class[] parameterTypes; //parameter types
}
Already thanks for helping :)
When you declare two classes with the same name in different packages, they are fundamentally different classes. That is why you are getting the exception when you attempt to cast from one type to the other.
The problem is that i cannot put the client package to the server or vice versa.
There is no way you can convince the Java type system that the two classes are the same. They are different.
The simplest solution is to create a third package that contains the classes that are needed on both the client and server side. Put the common package (or packages) into a JAR file, and add it to the classpath on the client and server sides.
There are other alternatives such as:
using a different marshalling / unmarshalling mechanism (JSON, XML, custom), or
using the available hooks in the Java serialization library to translate types (see #EJP's answer),
but (to mind) this problem is down to a design mistake, and the best approach is to fix that mistake soon rather than papering over it.
If you are passing objects from a java client to a java server via Java serialization, then you should be using the same classes on both sides. If that is not possible for a sound technical reason (as distinct from a design mistake), then that is most likely a good reason NOT to use Java serialization.
To answer your "real" questions:
Q: Can i determine the type of the class without importing the Package class from the package (client / server)?
Strictly yes, but it won't help you.
You can refer to a class by its fully qualified name; e.g.
if (o instanceof com.acme.WeaselTrap)
You can get the actual type's Class object.
Class<?> clazz = o.getClass();
But once you have gotten there, you still have the issue that the two types with the same names in different packages are fundamentally different.
(Of course, if your code can cope with the classes being different, you could make your life simpler by changing the class names so that the simple names are different.)
Q: Or is there a possibility to send the Object over the network without class information ?
Not using Java serialization.
The reason is obviously that he takes full path to determine the type of the object, so client.Package is not server.Package. The Problem is that i cannot put the client package to the server or vice versa.
You are just going to have to do exactly that, or put it into a third package that is accessible by both client and server.
Or else implement writeReplace() or readResolve() inside the classes, but that means that the class that does that has to know about the other class in the other package, which probably defeats your package issue as well in another way.
Shouldn't your instanceof be Package not package? Since it is a class name.
You can send the object back and forth as xml or json. The data can marshalled and unmarshalled to and from whatever classes you want.
For example:
Marshall/Unmarshall a JSON to a Java class using JAXB
The reason it isn't working is because you likely haven't implemented Java's serialization mechanism into your class. As described here, all you should have to do is have your class implement java.io.Serializable. Even if the absolute paths are different, if the code is the same in client.Package and server.Package this will work fine. Note that if you have any structures within your Package class that are not native Java types, those will also have to implement java.io.Serializable.

Different behaviour of Class literal and Class.forName for package local classes

Only for example lets consider the class ClassFileAssembler from the sun.reflect package.
This class is a package local class:
class ClassFileAssembler implements sun.reflect.ClassFileConstants {...
So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.
However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.
If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?
Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;
Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.
However we still able to get the ClassFileAssembler class object:
Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");
It works fine and gives us a full class description.
So, the questions are:
1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?
2) Why do they have such different security checks?
3) What's the reason to protect .class reference in such way?
4) Do these techniques use different class loaders?
Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.
The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.
The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)
The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.
If you check the javadoc of Class#forName, you will see that:
Note that this method does not check whether the requested class is accessible to its caller.
there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
everyone could access the Class instances, but the fields are protected.
in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
i dont think so.

Groovy 2.0.1, GroovyCastException on my own class?

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.

Categories