Why is this class being involved in serialization - java

I am getting the following serialization error and I am trying to read my object that I saved to a file
java.io.InvalidClassException: com.testGame.scoreCard; Incompatible class (SUID): com.testGame.scoreCard: static final long serialVersionUID =-5895378336422852901L; but expected com.testGame.scoreCard: static final long serialVersionUID =0L;
at java.io.ObjectInputStream.verifyAndInit(ObjectInputStream.java:2376)
at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1658)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:683)
at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1799)
at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:787)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1999)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1956)
But what I don't get is why scoreCard is serialized in the first place? The class(object) that I am writing and reading is serialized and does not call or make use of scoreCard class. Why would it complain about that class? Is there a way to see why this scoreCard is involved? ( I am using eclipse btw)
Thank you

Are you perhaps serializing an inner class of ScoreCard? They have secret references to the containing object.

Could it be that class that you are trying to restore depends indirectly on ScoreCard, through another class for example?
To see dependencies in Eclipse you can click on a class name or method name and press Ctrl+Shift+G, it will show you all the places where class or method is used.
Another way to discover dependencies is to click on a method name and press Ctrl+Alt+H, it will show you call graph that you can discover further.

Related

Bytebuddy get value of proteced field

Im struggling to figure out how to access a protected field using ByteBuddy and what approach to take.
Background: Id like to intercept a class from a dependency I have on my class path. Im creating a junit test report and need to intercept org.assertj.core.api.AbstractAssert in order to capture the actual field value from that class.
Iv tried...
Class<?> type = new ByteBuddy()
.redefine(AbstractAssert.class)
.visit(Advice.to(MyAdvices.class).on(ElementMatchers.isMethod()))
.make().load(AbstractAssert.class.getClassLoader()).getLoaded();
log.info(type.getFields().toString());
Class already loaded: class org.assertj.core.api.AbstractAssert
Im not even sure if this is the correct approach for what Im trying to achieve
Any help appreciated
You cannot just change a class on the JVM. Either you would need to use a different class loader and load the class regularly, or a Java agent. For an agent, Byte Buddy supplies a RedefinitionStrategy which you can use to integrate this in your above example. Also have a look at the byte-buddy-agent project.

Under what circumstances will a ByteBuddy proxy class be unable to access its own defined private fields?

I'm trying to understand this inscrutable error message:
java.lang.IllegalStateException: Cannot access private final com.foo.TestMethodInvoker$Foo com.bar.$MyProxy.methodHousing from class com.bar.$MyProxy
at net.bytebuddy.implementation.MethodCall$TargetHandler$ForField$Location$ForExplicitField.resolve(MethodCall.java:2406)
at net.bytebuddy.implementation.MethodCall$TargetHandler$ForField$Factory.make(MethodCall.java:2444)
at net.bytebuddy.implementation.MethodCall$Appender.<init>(MethodCall.java:3500)
at net.bytebuddy.implementation.MethodCall.appender(MethodCall.java:676)
at net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$ForImplementation.compile(MethodRegistry.java:233)
at net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$ForImplementation.compile(MethodRegistry.java:205)
at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared.compile(MethodRegistry.java:740)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:218)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:204)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3595)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3819)
I have a unit test (TestMethodInvoker) that defines a public static nested class named Foo.
My ByteBuddy recipe defines a private final com.foo.TestMethodInvoker$Foo field named methodHousing.
I use FieldAccessor.of to do various things with this field. (Or I'm trying to!)
The error message appears to be telling me that my proxy class cannot access its own private field (!).
Under what circumstances would this be true? Or what have I done wrong?
You are running into a bug which I just fixed on the master branch. This will be released in Byte Buddy 1.10.14.
If you want to avoid this bug in the meantime, avoid the explicit field reference as an argument but supply a matcher that resolves the field.

readObject throwing ClassNotFoundException when deserializing objects from independent class [duplicate]

I'm trying to pick up Java and wanted to test around with Java's client/server to make the client send a simple object of a self defined class(Message) over to the server. The problem was that I kept getting a ClassNotFoundException on the server side.
I think the rest of the codes seem to be alright because other objects such as String can go through without problems.
I had two different netbeans projects in different locations for client and server each.
Each of them have their own copy of Message class under their respective packages.
Message class implements Serializable.
On the client side, I attempt to send a Message object through.
On the server side, upon calling the readObject method, it seems to be finding Message class from the client's package instead of it's own. printStackTrace showed: "java.lang.ClassNotFoundException: client.Message" on the server side
I have not even tried to cast or store the object received yet. Is there something I left out?
The package name and classname must be exactly the same at the both sides. I.e. write once, compile once and then give the both sides the same copy. Don't have separate server.Message and client.Message classes, but a single shared.Message class or something like that.
If you can guarantee the same package/class name, but not always whenever it's exactly the same copy, then you need to add a serialVersionUID field with the same value to the class(es) in question.
package shared;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}
The reason is, that the readObject() in ObjectInputStream is practically implemented as:
String s = readClassName();
Class c = Class.forName(s); // Here your code breaks
Object o = c.newInstance();
...populate o...

Use Constants interface in GWT Project

I have not yet used Constants interface in GWT and I am having problem to run the example CellTable. The deferred binding fails and the central error message is: "No resource found for contactDataBaseCategories". contactDataBaseCategories is a method defined in the interface DataBaseConstants and returns an array of Strings. I suspect I must create a properties (txt?) file and to define the categories, but I am not sure, since I come across this case for the first time. How can I do it properly to make the example of the CellTable run?
Update: I have created the ContactDatabase.DatabaseConstants.properties file in the same package in which the interface is declared, I have added the line in the file:
contactDataBaseCategories = friends, coWorkers, other
but it still does not work. The error is again : "No resource found for contactDataBaseCategories" and then
"Deferred Binding failed for com.al.celltablöeexample.ContactDatabase.DatabaseConstants".
What going wrong?
This is how i do it
Constant interface
public interface DataBaseConstants extends Constants
{
#Key("contact-database-categories")
String contactDataBaseCategories();
}
property file. DataBaseConstants.properties
contact-database-categories = "Your String"
You can use it
public DataBaseConstants dbConstant= GWT.create( DataBaseConstants .class );
dbConstant.contactDataBaseCategories();
Edited
If you want to pass string array then you can do it like this
#DefaultStringArrayValue({"cat1", "cat2", "cat3", "cat4", "cat5"})
String[] contactDataBaseCategories();
More about Constants
I have finally managed it. The problem was that it could not find the resource/file: ContactDatabase.DatabaseConstants.properties. I have changed it to DatabaseConstants.properties and I removed the inner interface to its own file. The same I did in the class CwCellTable on the interface CwConstants. In the example page moreover, the instantiation of the CwConstants interface is missed, and one must do also this (in the constructor), like in the ContactDatabase class.
Just to add to Dilantha's answer you can then set
contact-database-categories = Family, Friends, Coworkers, Businesses, Contacts
in order to comply with the example.
Tip : In order to make the example work create a costructor in CwCellList and add the following :
initWidget(onInitialize());

SerialVersionUID with "private static final long" still gets InvalidClassException

I have compiled and jarred the various projects in my Java application, generating serialVersionUIDs automatically through Eclipse for all my classes derived from Serializable.
I read the answers to this question, and verified that serialVersionUids are all private static final long.
Nevertheless, I get an error like this when I try to run:
java.io.InvalidClassException: com.acme.product.Widget; local class
incompatible: stream classdesc serialVersionUID = 5226096973188250357, local
class serialVersionUID = -5432967318654384362
What am I missing?
You probably have a classpath issue, where your program is resolving an older incompatible version of the class which has a different value for serialVersionUID.
Or the serialized object that is being loaded, was serialized with an oder version of the class which is now unavailable.
If the class has changed since you serialized it, the change may be incompatible. Serialization can't deserialize it, even with the included serialVersionUID.
If you have the class as it was when serialized (e.g. from SCM), then try reverting back to that, regenerate the serialVersionUID and rerun.
If you have made incompatible changes, then you will have to implement readObject() /writeObject() to handle the serialization details yourself.
stream classdesc serialVersionUID =
5226096973188250357
What am I missing?
What you are missing is private static final long serialVersionUID = 5226096973188250357L;
However if the changed class is no longer serialization-compatible (see the Object Serialization Specification) you may now get more obscure errors.

Categories

Resources