views:

304

answers:

4

Hi,

I have the following problem: I want to send a type (java.lang.Class) over the wire and 'define' the class on the other side.

I tried like that:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(MyClass.class);

and on the receiving end:

ByteArrayInputStream bis = new ByteArrayInputStream(request.getBytes());
ObjectInputStream ois = new ObjectInputStream(bis);
Class c = (Class) ois.readObject(); // ClassNotFoundException

so obviously I need to send the raw bytecode of the class and do a

ClassLoader.defineClass(bytes, ..

but unfortunately I fail to see how I can retrieve the bytcode of a loaded class. I'm searching for something like:

byte[] byteCode = MyClass.class.toByteArray();

Is this even possible with standard JDK or is there any small lib out there that can do that?

Thank you very much,

Pauli

A: 

You should check java serialization interface

edit :

I re-read your post and you're talking about defining the class on the other side. This lead me to think that what you're trying to accomplish is to distribute objects across the network.

Also, if both your server and client share the same interface, you can simply create objects via java reflection

Eric
It sounds like he needs to get the class DEFINITION across the wire, as opposed to an instance of a class. With technologies like RMI and even reflection, having the class DEFINITION available to the classloader is still a prerequisite.
Jared
Well, yes but the class loader can load the bytecode over the wire.
Tom Hawtin - tackline
A: 

You could write your own serialization method.

so

public byte[] Serialize() {

// serialize each field in turn here.

return data; }

public void Deserialize(byte[] data) {

// deserialize data in the same order it was serialized.

}

This is the method that we implement in .Net for serialization. The key thing with this method is it puts you in complete charge of serialization. It may be long winded if you're not going to have any versions of this type of communication but for multiple versions as the product grows this is one of the few reliable methods we've found to do it.

We use memory stream objects to write out each data field and cascade writing of complex objects by implementing the iserializable interface (which may not exist in java, but it's a simple interface to implement yourself).

We use the same dll on the corporate server as we do on the client.

Serialization is an issue no matter which platform you're on.

Peter
+5  A: 

I don't think what you want is possible in full generality. The act of defining a class from its bytecode is not reversible. What you should be able to do, however, is to directly read the bytecode file (assuming that it's an URLClassLoader):

MyClass.class.getResourceAsStream("Myclass.class")

Alternatively, you could just make the class files accessible via HTTP and directly use an URLClassLoader on the receiving side.

Michael Borgwardt
I think you would have to pull the contents of the .class file over the wire, then reconstitute it (either in file or in memory), and have a classloader load that file. If you reconstitute the .class file as a file, you can use the URLClassLoader. If you want to reconstitute it in memory, you probably need to define your own classloader.
Jared
You don't need to "reconstitute" it at all to use an URLClassLoader. It's not named *URL*ClassLoader for nothing - it will happily take a HTTP URL and do all the hard work itself. That's how it works with Applets, after all.
Michael Borgwardt
+1  A: 

You cannot do this from memory. You must have the byte codes defining the class, which for most classes can be found by asking the JVM. This code from http://www.exampledepot.com/egs/java.lang/ClassOrigin.html should get you started:

// Get the location of this class
Class cls = this.getClass();
ProtectionDomain pDomain = cls.getProtectionDomain();
CodeSource cSource = pDomain.getCodeSource();
URL loc = cSource.getLocation();  // file:/c:/almanac14/examples/
Thorbjørn Ravn Andersen