On Tuesday 19 June 2007 09:53, Andrew Haley wrote:
> Andrew Haley writes:
>  > Andrew John Hughes writes:
>  >  > Hi everyone,
>  >  >
>  >  > I've recently been trying to build JikesRVM on a Free platform (using
>  >  > CACAO and some hacked up tools from OpenJDK in the form of IcePick). 
>  >  > I've got it just about there now, but I've been let down by a missing
>  >  > native method.
>  >  >
>  >  > Within the java.util.concurrent framework, the class AtomicLong has a
>  >  > native method, VMSupportsCS8 which CACAO at least doesn't provide. 
>  >  > It's basically just a check method to find out whether the VM
>  >  > supports lockless compare-set operations on longs.
>  >  >
>  >  > >From java.util.concurrent.atomic.AtomicLong:
>  >  >
>  >  >     /**
>  >  >      * Records whether the underlying JVM supports lockless
>  >  >      * CompareAndSet for longs. While the unsafe.CompareAndSetLong
>  >  >      * method works in either case, some constructions should be
>  >  >      * handled at Java level to avoid locking user-visible locks.
>  >  >      */
>  >  >     static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
>  >  >
>  >  >     /**
>  >  >      * Returns whether underlying JVM supports lockless CompareAndSet
>  >  >      * for longs. Called only once and cached in
>  >  > VM_SUPPORTS_LONG_CAS. */
>  >  >     private static native boolean VMSupportsCS8();
>  >  >
>  >  > Has anyone implemented this so far?  So near, but yet so far!
>  >
>  > Yes, it's in libgcj, of course.
>  >
>  > jboolean
>  > java::util::concurrent::atomic::AtomicLong::VMSupportsCS8 ()
>  > {
>  >   // FIXME
>  >   return false;
>  > }
>
> Actually, I didn't quite tell you the *whole* truth: VMSupportsCS8 is
> also a gcj builtin.  The code in libgcj is a fallback that gets called
> only if libgcj is built with no optimization.
>
> Andrew.

I've tried gcj this weekend (from svn), after finding that it has both 
VMSupportsCS8 (as aph mentions above) and annotation support (which is where 
cacao fell down pretty finally, after twisti patched up the VMSupportsCS8 
hole).  I get an interesting failure from this, which perhaps others may be 
able to enlighten me on.  It seems a bit less straightforward than a simple 
missing method or feature...

     [echo] java.lang.NoClassDefFoundError: 
java.util.Collections$CheckedMap$CheckedEntrySet$1
     [echo]    at 
org.jikesrvm.classloader.VM_BootstrapClassLoader.loadVMClass(VM_BootstrapClassLoader.java:132)
     [echo]    at 
org.jikesrvm.classloader.VM_TypeReference.resolveInternal(VM_TypeReference.java:745)
     [echo]    at 
org.jikesrvm.classloader.VM_TypeReference.resolve(VM_TypeReference.java:719)
     [echo]    at 
BootImageWriter.createBootImageObjects(BootImageWriter.java:1018)
     [echo]    at BootImageWriter.main(BootImageWriter.java:614)
     [echo] Caused by: java.lang.IncompatibleClassChangeError: 
java.util.Collections$CheckedMap$CheckedEntrySet$1
     [echo]    at java.lang.VMClassLoader.defineClass(natVMClassLoader.cc:83)
     [echo]    at java.lang.ClassLoader.defineClass(ClassLoader.java:573)
     [echo]    at 
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:85)
     [echo]    at java.net.URLClassLoader.findClass(URLClassLoader.java:616)
     [echo]    at java.lang.ClassLoader.loadClass(ClassLoader.java:442)
     [echo]    at java.lang.ClassLoader.loadClass(ClassLoader.java:377)
     [echo]    at java.lang.Class.forName(natClass.cc:105)
     [echo]    at 
org.jikesrvm.classloader.VM_Type.createClassForType(VM_Type.java:506)

The problem is the java.lang.IncompatibleClassChangeError caused by trying to 
create a Class object for java.util.Collections$CheckedMap$CheckedEntrySet$1.  
This is thrown in _Jv_DefineClass (part of defineclass.c which is called by 
natVMClassLoader.cc above).   I narrowed this down using gdb to the method 
checkExtends((jclass sub 
= "java.util.Collections$CheckedMap$CheckedEntrySet$1", jclass super 
= "java.util.Collections$CheckedIterator")
and the failure of if (sub->loader != super->loader) for a non-public class 
(this anonymous class is a CheckedIterator implementation using by the 
CheckedEntrySet).

You can mimic this simply with:

public class TestClassLoading
{
  public static void main(String[] args)
    throws Exception
  {  
System.out.println(Class.forName("java.util.Collections$CheckedMap$CheckedEntrySet$1"));
  }
}

The class isn't in gcj, which I think may be the problem.  The example works 
fine with jamvm and cacao which has that class.  Putting either Classpath 
from my local copy or the JikesRVM build on the classpath causes the error.  
Otherwise, it's a ClassNotFoundException.  

Adding a line beforehand to try for CheckedIterator succeeds, so clearly the 
problem is that gcj has its own CheckedIterator but is loading this class 
from the jar file, so that the class loaders don't match.  This seems like a 
legitimate gcj error in that case, but that doesn't help with this corner 
case.  The code for the class is in the gcj libraries, so maybe it is being 
optimised out or something...?

Any help much appreciated,
Cheers,
-- 
Andrew :-)

Help end the Java Trap!
Contribute to GNU Classpath and the OpenJDK
http://www.gnu.org/software/classpath
http://openjdk.java.net

Attachment: pgpeEeAKwjraP.pgp
Description: PGP signature

Reply via email to