classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Loader in ObjectStreamClass.readClassDescriptor


From: Nicolas Geoffray
Subject: Re: Loader in ObjectStreamClass.readClassDescriptor
Date: Tue, 13 Sep 2005 23:11:37 +0200
User-agent: Mozilla Thunderbird 1.0.6 (X11/20050725)

Hi Mark,

Mark Wielaard wrote:

Hi Nicolas,

On Tue, 2005-08-02 at 14:08 +0200, Nicolas Geoffray wrote:
Hi everyone,

sorry for the typo, it was ObjectInputStream.readClassDescriptor that misbehaves.

Shortly, when a reading a given class descriptor CL, it loads the class of a field from CL with the currentClassLoader on the stack. But in RMI, the currentClassLoader is null, so loading the fields' classes won't work for classes that are not in the bootclasspath (glibj.zip). The algorithm with RMI will however succeed to load the class CL itself because it uses the method resolveClass from gnu.java.rmi.server.RMIObjectInputStream. The patch given fixes the problem by loading the fields' class of CL with CL's classloader.

I agree it looks like we are doing something dodgy here. Using the class
loader of the class itself to resolve the field classes seems better
then using the current class loader if resolveClass() is overridden.

Do you happen to have a little testcase for this?
Either using rmi or some other class that overrides
ObjectInputStream.resolveClass(). Then we can put that in Mauve.

Three files for testing are attached. It's more an RMI related issue, since the thread class for rmi is gnu.java.rmi.server.UnicastConnection, which is loaded by the vm classloader.
Consequence is that the current classloader in stack is null.

ReceiveObjectImpl is the RMI object. Just rmic and launch it. Then launch Main.

While we're at it, there might also be something to change in, this time, ObjectStreamClass.setClass. In the method it tries to compare the serial uids bewteen the local class and the stream class. It does it for all classes, even for array classes, which is wrong because array classes do not have serial uids.

An array class does have a serial uid. But it is calculated slightly
differently because we have to pretend an array class does not implement
any interfaces.
I thought arrays do not have uids because their implementation is native. How can you calculate an uid for a native type?

I'm also interested to know how compatible are the algorithms between java and gnu classpath for computing the serial version uid? When I tried to communicate a sun vm with mine, it says that my HelloWorld class isn't compatible between the vms. Is that
normal or are the algorithms compatibles and I did something wrong?

The algorithms should be compatible. But since compilers can generate
different class members (like synthetic methods or inner class names) a
class compiled with different (versions of) compilers might not have the
same serial version uid. See also:
http://www.gnu.org/software/classpath/docs/hacking.html#SEC18

OK, thanks

Cheers,

Mark

Cheers,
Nicolas
import java.rmi.Naming;

public class Main{

  class Foo implements java.io.Serializable{}

  class Bar implements java.io.Serializable{
    Foo f = new Foo();
  }
    
  public static void main(String[]args){

    try{
      Bar b = new Bar();
      ReceiveObject ref = (ReceiveObject) 
Naming.lookup("rmi://localhost/ReceiveObject");
      ref.receiveObject(b);
    }catch(Exception e){
      System.out.println("Error : " + e );
    }
  }
}
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface ReceiveObject extends Remote{
  public Object receiveObject(Object unknown)
                throws RemoteException;
}
import java.rmi.*;
import java.rmi.server.*;


public class ReceiveObjectImpl extends UnicastRemoteObject implements 
ReceiveObject{

  public ReceiveObjectImpl() throws RemoteException{
  }

  public Object receiveObject(Object unknown)
    throws RemoteException{
      System.out.println(unknown);
      return null;
    }

  public static void main(String[] args){
    try{
      ReceiveObject ref = new ReceiveObjectImpl();
      Naming.rebind("ReceiveObject", ref);
    }catch(Exception e){
      e.printStackTrace();
    }
  }
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]