Lambda class names no longer reported when listening for JVMTI_EVENT_CLASS_FILE_LOAD events

Frost, Gary Gary.Frost at amd.com
Fri Jan 24 08:47:46 PST 2014


So is this an artifact of using the hash code of the class as the /XXXXXX
suffix. 

As I mentioned below the classname in the bytes representing these VM
anonymous classes do not contain the suffix whereas the reflected name
does. 
 
At first I was surprised, until I realized how non-trivial it was to
create class bytes for a class whose name depends on the hashcode of the
name of the class. It hurt my head thinking of this.

I really think that the reflected name of all classes should match the
name inside the classfile.  Aparapi can¹t be the only byte code inspection
tool which makes this assumption.

Gary 

On 1/24/14, 10:26 AM, "Joel Borggrén-Franck" <joel.franck at oracle.com>
wrote:

>Hi Peter,
>
>Back then I filed https://bugs.openjdk.java.net/browse/JDK-8029100
>
>feel free to assign to you if you have a fix.
>
>cheers
>/Joel
>
>On 24 Jan 2014, at 17:07, Peter Levart <peter.levart at gmail.com> wrote:
>
>> On 01/24/2014 12:48 AM, John Rose wrote:
>>> Background on anonymous classes:
>>> 
>>> They are a private feature of the HotSpot JVM implementation.
>>>Naturally, compilers and other tightly-coupled tools have to know about
>>>them.
>>> 
>>> They don't have names, at least in the sense of something you could
>>>use to look up via a class loader.  What names they display are (as you
>>>see) derived from their bytecodes, but they do not function as regular
>>>class names.
>>> 
>>> Specifically, if someone tries to use the supposed name of an
>>>anonymous class with Class.forName or ClassLoader.loadClass, the result
>>>will be ClassNotFoundException.
>>> 
>>> The mangled suffix /XXXXX on Class.getName string provides an extra
>>>hint as to what is wrong.  (The XXXXX value happens to be the class's
>>>hash code, which makes it easier to distinguish classes with the same
>>>supposed name.)  Since slash '/' is an illegal element of class names,
>>>there's no ambiguity about how the name got that way.
>>> 
>>> HTH
>>> 
>>> ‹ John
>> 
>> Hi John,
>> 
>> Not long ago I found a special corner case where the following
>>expression:
>> 
>> 
>>     Class.forName(clazz.getName(), clazz.getClassLoader()) == clazz
>> 
>> 
>> ...evaluates to false. Here's an example that demonstrates this:
>> 
>> 
>> public class AnnonClassTest {
>> 
>>     static class C {}
>> 
>>     public static void main(String[] args) throws Exception {
>>         String cClassResourceName = C.class.getName().replace('.', '/')
>> + ".class";
>>         URL cClassUrl =
>> C.class.getClassLoader().getResource(cClassResourceName);
>>         byte[] bytes = new byte[4096];
>>         try (InputStream in = cClassUrl.openStream();
>> ByteArrayOutputStream out = new ByteArrayOutputStream()) {
>>             for (int nread = in.read(bytes); nread >= 0; nread =
>> in.read(bytes)) {
>>                 out.write(bytes, 0, nread);
>>             }
>>             bytes = out.toByteArray();
>>         }
>> 
>>         Field uf = Unsafe.class.getDeclaredField("theUnsafe");
>>         uf.setAccessible(true);
>>         Unsafe u = (Unsafe) uf.get(null);
>> 
>>         Class<?> cAnnonClass = u.defineAnonymousClass(C.class, bytes,
>> new Object[0]);
>> 
>>         System.out.println(C.class.getName());
>>         System.out.println(cAnnonClass.getName());
>>         System.out.println(C.class == cAnnonClass);
>>         System.out.println();
>> 
>>         Class<?> cArrayClass = C[].class;
>>         Class<?> cAnnonArrayClass = Array.newInstance(cAnnonClass,
>> 0).getClass();
>> 
>>         System.out.println(cArrayClass.getName());
>>         System.out.println(cAnnonArrayClass.getName());
>>         System.out.println(cArrayClass == cAnnonArrayClass);
>>         System.out.println();
>> 
>>         Class<?> whichArrayClass =
>> Class.forName(cAnnonArrayClass.getName());
>>         System.out.println(whichArrayClass == cArrayClass);
>>         System.out.println(whichArrayClass == cAnnonArrayClass);
>>     }
>> }
>> 
>> 
>> 
>> This prints the following:
>> 
>> 
>> AnnonClassTest$C
>> AnnonClassTest$C/2101973421
>> false
>> 
>> [LAnnonClassTest$C;
>> [LAnnonClassTest$C;
>> false
>> 
>> true
>> false
>> 
>> 
>> Do you agree it would be more correct if the name of the array of the
>> anonymous class in above example was:
>> 
>> 
>> [LAnnonClassTest$C/2101973421;
>> 
>> 
>> This would work more consistently then (throwing ClassNotFoundException
>> when trying to obtain such class by name).
>> 
>> 
>> Regards, Peter
>> 
>> 
>>> 
>>>> Gary
>>>> 
>>>> ________________________________________
>>>> From: Brian Goetz [brian.goetz at oracle.com]
>>>> Sent: Thursday, January 23, 2014 7:48 AM
>>>> To: Frost, Gary
>>>> Cc: lambda-dev at openjdk.java.net
>>>> Subject: Re: Lambda class names no longer reported when listening for
>>>>JVMTI_EVENT_CLASS_FILE_LOAD events
>>>> 
>>>> Yes.  We moved to "anonymous classes" (in the sense of
>>>>Unsafe.defineAnonymousClass, not anonymous inner classes), for reasons
>>>>of both security and performance.  This is an unfortunate side effect.
>>>> 
>>>> On Jan 22, 2014, at 5:33 PM, Frost, Gary wrote:
>>>> 
>>>>> Not sure when this change came about but I just started using
>>>>> 
>>>>> java version "1.8.0-ea"
>>>>> Java(TM) SE Runtime Environment (build 1.8.0-ea-b124)
>>>>> 
>>>>> I noticed that the JVMTI agent I use to  listen for
>>>>>JVMTI_EVENT_CLASS_FILE_LOAD events is no longer seeing events for the
>>>>>dynamically create classes created to encapsulate 'captured' args.
>>>>>Or possibly the class events are triggeted, but the 'name' is NULL. I
>>>>>am seeing an increase in the number of a events reported NULL as the
>>>>>name.
>>>>> 
>>>>> The Aparapi project listens for these events so we can determine the
>>>>>captured args for a given lambda.  These are the synthetic classes
>>>>>created on the fly by the method handle factory.
>>>>> 
>>>>> This had been working fine until recently.  Is there a reason we
>>>>>would stop generating  these, or is this just a regression?
>>>>> 
>>>>> Gary
>>>>> 
>>>> 
>>>> 
>>>> 
>>> 
>> 
>> 
>
>




More information about the lambda-dev mailing list