Find serialization usage - java

I'm mantaining some application and I have a class marked as Serializable but I suspect that is not being serialized anywhere so the Serializable mark is not needed.
What is the best way to be sure of that? It's possible to determine this statically?
Thanks

Not directly. Generally, serialization happens when the object is being written to ObjectOutputStream, but this most often happen outside of your code (for example in libraries you are using, or in your container). So you have two options:
dynamically - define this method on your class. Thus you will eventually know if the class is being serialized, without breaking any functionality. But you'd need the system to be running:
private void writeObject(java.io.ObjectOutputStream out) {
out.defaultWriteObject();
log.info("Object of type " +
getClass().getName() + " is being serialized");
// optionally include a stacktrace here, or use a debugger, to see
// when exactly it happened
}
try to understand where is your object going. If it transferred over a network, or stored in a temporary storage (session, cache), then it should be Serializable. Otherwise, most probably, not.

I think it's impossible to determine statically, at least very hard - your object can be a part of non-generic collection, it can be used by reflection, etc.
What you can do is put some logging/debugging code in objects' readResolve() and writeReplace() methods, that are called by jvm when the object is serialized/deserialized.

I'm quite sure, that it can't be checked statically, except you don't use external libraries at all (which will not result in serious programs)
Perhaps you are using some sort of ORM like Hibernate, which in some cases need to have serializable object, or your object has to be sent through Web-Service or other middleware stacks like Corba where a serialization is done implicitly (when the object is marked as such).
What's the purpose of your class?

Related

Not serializable class with strings only [duplicate]

We work heavily with serialization and having to specify Serializable tag on every object we use is kind of a burden. Especially when it's a 3rd-party class that we can't really change.
The question is: since Serializable is an empty interface and Java provides robust serialization once you add implements Serializable - why didn't they make everything serializable and that's it?
What am I missing?
Serialization is fraught with pitfalls. Automatic serialization support of this form makes the class internals part of the public API (which is why javadoc gives you the persisted forms of classes).
For long-term persistence, the class must be able to decode this form, which restricts the changes you can make to class design. This breaks encapsulation.
Serialization can also lead to security problems. By being able to serialize any object it has a reference to, a class can access data it would not normally be able to (by parsing the resultant byte data).
There are other issues, such as the serialized form of inner classes not being well defined.
Making all classes serializable would exacerbate these problems. Check out Effective Java Second Edition, in particular Item 74: Implement Serializable judiciously.
I think both Java and .Net people got it wrong this time around, would have been better to make everything serializable by default and only need to mark those classes that can't be safely serialized instead.
For example in Smalltalk (a language created in 70s) every object is serializable by default. I have no idea why this is not the case in Java, considering the fact that the vast majority of objects are safe to serialize and just a few of them aren't.
Marking an object as serializable (with an interface) doesn't magically make that object serializable, it was serializable all along, it's just that now you expressed something that the system could have found on his own, so I see no real good reason for serialization being the way it is now.
I think it was either a poor decision made by designers or serialization was an afterthought, or the platform was never ready to do serialization by default on all objects safely and consistently.
Not everything is genuinely serializable. Take a network socket connection, for example. You could serialize the data/state of your socket object, but the essence of an active connection would be lost.
The main role of Serializable in Java is to actually make, by default, all other objects nonserializable. Serialization is a very dangerous mechanism, especially in its default implementation. Hence, like friendship in C++, it is off by default, even if it costs a little to make things serializable.
Serialization adds constraints and potential problems since structure compatibility is not insured. It is good that it is off by default.
I have to admit that I have seen very few nontrivial classes where standard serialization does what I want it to. Especially in the case of complex data structures. So the effort you'd spend making the class serializble properly dwarves the cost of adding the interface.
For some classes, especially those that represent something more physical like a File, a Socket, a Thread, or a DB connection, it makes absolutely no sense to serialize instances. For many others, Serialization may be problematic because it destroys uniqueness constraints or simply forces you to deal with instances of different versions of a class, which you may not want to.
Arguably, it might have been better to make everything Serializable by default and make classes non-serializable through a keyword or marker interface - but then, those who should use that option probably would not think about it. The way it is, if you need to implement Serializable, you'll be told so by an Exception.
I think the though was to make sure you, as the programmer, know that your object my be serialized.
Apparently everything was serializable in some preliminary designs, but because of security and correctness concerns the final design ended up as we all know.
Source: Why must classes implement Serializable in order to be written to an ObjectOutputStream?.
Having to state explicitely that instances of a certain class are Serializable the language forces you to think about if you you should allow that. For simple value objects serialization is trivial, but in more complex cases you need to really think things through.
By just relying on the standard serialization support of the JVM you expose yourself to all kinds of nasty versioning issues.
Uniqueness, references to 'real' resources, timers and lots of other types of artifacts are NOT candidates for serialization.
Read this to understand Serializable Interface and why we should make only few classes Serializable and also we shopuld take care where to use transient keyword in case we want to remove few fields from the storing procedure.
http://www.codingeek.com/java/io/object-streams-serialization-deserialization-java-example-serializable-interface/
Well, my answer is that this is for no good reason. And from your comments I can see that you've already learned that. Other languages happily try serializing everything that doesn't jump on a tree after you've counted to 10. An Object should default to be serializable.
So, what you basically need to do is read all the properties of your 3rd-party class yourself. Or, if that's an option for you: decompile, put the damn keyword there, and recompile.
There are some things in Java that simply cannot
be serialized because they are runtime specific. Things like streams, threads, runtime,
etc. and even some GUI classes (which are connected to the underlying OS) cannot
be serialized.
While I agree with the points made in other answers here, the real problem is with deserialisation: If the class definition changes then there's a real risk the deserialisation won't work. Never modifying existing fields is a pretty major commitment for the author of a library to make! Maintaining API compatibility is enough of a chore as it is.
A class which needs to be persisted to a file or other media has to implement Serializable interface, so that JVM can allow the class object to be serialized.
Why Object class is not serialized then none of the classes need to implement the interface, after all JVM serializes the class only when I use ObjectOutputStream which means the control is still in my hands to let the JVM to serialize.
The reason why Object class is not serializable by default in the fact that the class version is the major issue. Therefore each class that is interested in serialization has to be marked as Serializable explicitly and provide a version number serialVersionUID.
If serialVersionUID is not provided then we get unexpected results while deserialzing the object, that is why JVM throws InvalidClassException if serialVersionUID doesn't match. Therefore every class has to implement Serializable interface and provide serialVersionUID to make sure the Class presented at the both ends is identical.

"Passing arguments" via ThreadLocal ok?

I'm building both a Java networking library and an application which makes use of it. The library consists of:
An interface PacketSocket which has methods for sending and receiving packets of bytes.
Two implementations of it, one over TCP and one over UDP.
An ObjectConnection class which is built on top of a PacketSocket and handles serialization of objects to byte packets.
The application uses RequestConnection on top of a UDPPacketSocket. The UDPPacketSocket implementation is unique in that it supports specifying per packet whether delivery should be guaranteed. I would like to be able to use from within the application, but there is no way through the ObjectConnection and PacketSocket interfaces.
I could of course add a boolean guaranteed parameter to the applicable methods in those interfaces, but then I'd eventually (when there will be more implementations of PacketSocket) have to add many more parameters that are specific to certain implementations only and ignored by others.
Instead I though I could do it with a static thread-local property of UDPPacketSocket, like so:
class Application {
public void sendStuff() {
// is stored in a ThreadLocal, so this code is still thread-safe
UDPPacketSocket.setGuaranteed(true);
try {
myObjCon.send(...);
} finally {
// ... restore old value of guaranteed
}
}
}
What do you think of an approach like that?
I think its an ugly hack, however sometimes it is only option, esp if you are "passing" a value through many layers of code and you cannot easily modify that code.
I would avoid it if you can. A better option would be to have the following, if possible
myObjCon.sendGuaranteed(...);
I agree that this is an ugly hack. It will work, but you may end up regretting doing it.
I'd deal with this by using a Properties object to pass the various PacketSocket implementation parameters. If that is unpalatable, define a PacketSocketParameters interface with a hierarchy of implementation classes for the different kinds of PacketSocket.
i'd recommend some sort of "performance characteristics" parameter, maybe something like a Properties instance. then, each impl could use their own, arbitrary properties (e.g. "guaranteed" for your current impl). note, you can avoid string parsing by using the object methods on Properties (e.g. get() instead of getProperty()) or using a straight Map instance. then your values could be true objects (e.g. Boolean).
since we know it's a UDP, we can de-abstract the layers and access the concrete stuff
( (UDPSocket)connection.getSocket() ).setGuaranteed(true);

Is it safe to use bytecode enhancement techniques on classes that might be serialized and why?

I haven't tried this yet, but it seems risky. The case I'm thinking of is instrumenting simple VO classes with JiBX. These VOs are going to be serialized over AMF and possibly other schemes. Can anyone confirm or deny my suspicions that doing behind-the-back stuff like bytecode enhancement might mess something up in general, and provide some background information as to why? Also, I'm interested in the specific case of JiBX.
Behind the scenes, serialization uses reflection. Your bytecode manipulation is presumably adding fields. So, unless you mark these fields as transient, they will get serialised just like normal fields.
So, provided you have performed the same bytecode manipulation on both sides, you'll be fine.
If you haven't you'll need to read the serialisation documentation to understand how the backwards compatibility features work. Essentially, I think you can send fields that aren't expected by the receiver and you're fine; and you can miss out fields and they'll get their default values on the receiving end. But you should check this in the spec!
If you're just adding methods, then they have no effect on serialisation, unless they are things like readResolve(), etc. which are specifically used by the serialisation mechanism.
Adding/changing/removing public or protected fields or methods to a class will affect it's ability to be deserialized. As will adding interfaces. These are used among other things to generate a serialVersionUID which is written to the stream as part of the serialization process. If the serialVersionUID of the class doesn't match the loaded class during deserialization, then it will fail.
If you explicitly set the serialVersionUID in your class definition you can get by this. You may want to implement readObject and writeObject as well.
In the extreme case you can implement Externalizable and have full control of all serialization of the object.
Absolute worst case scenario (though incredibly useful in some situations) is to implement writeReplace on a complex object to swap it out with a sort of simpler value object in serialization. Then in deserialization the simpler value object can implement readResolve to either rebuild or locate the complex object on the other side. It's rare when you need to pull that out, but awfully fun when you do.

How to cache *any* object type to memory/disk in java?

Is there a generic way to cache any type of object (be in a java class, or a word document etc.) to memory or disk?
Is simply serializing the object, and retaining the file extension (if it has one) enough to rebuild the object?
You seems to be using the word Object to describe 2 different things.
If your object is a Java object then having that object implement the Serializable is enough if you then use the java methods to serialize/de-serialize the object.
If you want to cache arbitrary data from the filesystem, the best way is to read it in an byte array(Or ArrayList). Then you can just write the array back to the disk or where you want it.
If you're talking about the inbuilt Java serialization, then you wouldn't even need to retain the file extension. The serialized form has enough information such that the deserialization process will produce an identical object without any additional help. I suppose that depending on how your code is structured, though, you might need to store some metadata for your own benefit so that you know what to cast the resulting Object as.
Note that Java serialization doesn't seem to fit your requirements, though - it cannot serialize any type of object, only those that implement Serializable. Perhaps you need to think a little more about what you mean by "simply serializing the object", since that's the rub.
No.
There is a class of objects which cannot be deserialized in a meaningful way. Think of an open network connection which is in the middle of transferring a file. You can not store that to disk, close your app, open your app, deserialize that connection and expect that it "just continues".
Java has an interface Serializable which indicates that an object can be serialized. It's up to you to ensure that is indeed possible. Typically an object is Serializable if all the data it holds is Serializable, or that data which is not Serializable is marked transient.
This is not to say that you could not, theoretically, dump the memory contents to a file as a byte stream, and read it back again later. You could build something like that I suppose. But to expect that it works is a different thing altogether.
In short, it is not possible to serialize any type. However, there is a generic way to serialize Java objects which are marked to be Serializable.
Not sure what you mean by "or a word document". Serialization can be used for disk caching, not sure what the purpose of using it in memory would be since it would probably be far faster to simply keep the original object.
A more robust solution might be ehcache it can manage the size of the cache as well as moving it between memory and disk.
If you're wondering about the cross platform (disk or memory) persistence part of the question, look at Java's Preferences class.
My, what a lot of answers!
Any object can make itself serializable by implementing java.io.Serializable.
But:
A default serialiser is implemented in ObjectOutputStream, which simply walks the object tree. This is fine for simple javabean type objects, but it can have undesirable effects such as system objects being serialised (I once inspected a serialised java object file and found that it was including all of the system timezone objects). And, of course, if your object has objects inside it that are not serializable (and not transient), then ObjectOutputStream will throw an exception.
(actually, even for JavaBean objects the default serializer it awful - the default serializer emits the classname of java.lang.String for every string field.)
So if your object is complicated, then you really should implement Externalizable and write a serialiser and deserializer with some smarts.
http://download.oracle.com/javase/6/docs/platform/serialization/spec/serial-arch.html#7185
So basically - no, you can't serialise any old object. You have to design object that are intended to be serialised and, ideally, that have some smarts about how they get themselves to and from a stream.
You cannot serialize any object in Java. Moreover, Java uses shallow copying(or is it called something else) for serialization, so if you want to seialize something like a HashMap, it might not save your data.

Passing Objects as part of SOAP Request and Getting Objects back as Response....using webservices

I have a webservice, which takes java.lang.object objects as parameters (because at runtime only know hte type of object)...after doing process, reply response setting java.lang.Object to it.
I am able to send the reuest objects to webservice from calling program, but getting NotSerializable exception while building the response from webservice.
I came to know that 'if we implement, java.io.serializable, the mebmers also should be serializable objects'... here Object isnot a serializable object..it doesn't impllement Serializable....
If anyone could guide mw with right solution..I wouold be thankful.
Thanks
Bhaskar
I have a webservice, which takes
java.lang.object objects as parameters
(because at runtime only know hte type
of object)
This part worries me. Not knowing the type while programming is a code smell. If you have no idea what it is, how can you make code to handle it?
There could be a legitimate reason to do what you are trying to accomplish, but usually there is a better way. The real question here may be: "How should I design my webservice and code, to handle my requirements?"
When a method accepts "Object" or other extremely general types, they often contain a switch-like structure which checks for certain types and handles them differently, and "unknown" types either throws an exception, or (worse) may simply be ignored.
The solution here is probably to create a new method for each type.
And it doesn't really matter if it is just a usual Java method, or if it is a webservice.
Serialize the object to a Byte Array, and return that in your SOAP call, then marshall the object back from the Byte Array in the client. SOAP can readily and efficiently handle Byte Arrays, and the Serialization will be an implementation detail outside the scope of the SOAP transaction.
To solve your immediate problem, you should accept a "Serializable" in stead of "Object". Then you need to make your class serializable. If you can't do that, you will never be able to transfer the object over a webservice.
This is the core you must understand: If it can be transferred over a webservice, that means it is possible to serialize it. If it is possible to serialize it, it is possible to make it a Serializable.
If you can't modify the class itself, you can work around the problem. For example you can create a new Serializable class, which can read all relevant info from your object.
To say that all members of a Serializable class needs to Serializable too is not the complete truth. All needed data needs to be serializable, but the classes themselves does not need to implement the Serializable interface.
The alternative is to implement these two methods:
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, classNotFoundException;
There is an article about serialization here: Discover the secrets of the Java Serialization API
It describes how to use these two methods under "Customize the Default Protocol".
If that isn't advanced enough, keep in reading under "Create Your Own Protocol: the Externalizable Interface" to see how to implement the Externalizable interface (a subinterface to Serializable), which gives you complete control over the serialization process.
(I am ignoring the "transient" feature for simply ignoring non-serializable data, since I assume that you need them. If my assumption is wrong, read the part "Nonserializable Objects".)
If the members of the class don't implement Serializable then you can't use native Java serialisation for it. That's basically what your error message is telling you.
If you cannot cause the underlying objects to implement Serializable, then you are probably going to have to find a different method of serialisation for passing in and out of your web service. Popular varieties from Java are XML, JSON, AMF, although you can always roll your own.
If you have Java objects on either end of your request then make sure you factor your code so that your serialisation and de-serialisation code is in a library that can be used at both ends. That will greatly ease the burden of testing in your implementation.
I would recommend keeping all the serialisation code out of the domain objects themselves. Think about using a factory pattern for creation of your objects.
HTH

Categories