java.lang.constant.ClassDesc and TypeDescriptor for hidden class??

Mandy Chung mandy.chung at oracle.com
Mon Apr 13 19:09:25 UTC 2020



On 4/12/20 5:14 AM, Remi Forax wrote:
>> The problem is not that 'c' is easier to parse, but that 'c`' is not
>> parsable at all. Do we really want unparsable method descriptors?
>>
>> If the problem is preventing resolving of hidden class names or
>> descriptors, then it seems that making the method descriptors unparsable
>> is not the right place to do that.
> I agree with Peter,
> throwing an exception is better, there is no way to encode a hidden class in a descriptor because a hidden class has no name you can lookup,
> if the API return an unparsable method descriptor, the user code will throw an exception anyway.
>

Several points that are noteworthy:

1. A resolved method never has a hidden class in its signature as a 
hidden class cannot be discovered by any class loader.

2. When VM fails to resolve a symbolic reference to a hidden class, it 
might print its name or descriptor string in the error message. Lois and 
Harold can confirm if this should or should not cause any issue (I can't 
see how it would cause any issue yet).

3. The only way to get a method descriptor with a hidden class in it is 
by constructing `MethodType` with a `Class` object representing a hidden 
class.

4. `Class::descriptorString` on a hidden class is human-readable but not 
a valid descriptor (both option c and c')

5. The special character chosen by option c and c' is an illegal 
character for an unqualified name ("."  ";" "[" "/" see JVMS 4.2.2).  
This way loading a class of the name of a hidden class will always get 
CNFE via bytecode linkage or Class::forName etc (either from 
Class::getName or mapped from Class::descriptorString).

For existing tools that map a descriptor string by trimming "L;" 
envelope and/or replacing "/" with ".",  "Lfoo/Foo;/123Z" (option c') 
may be mapped to "foo.Foo" and ".123Z" (if used ";" as a separator) or 
"foo.Foo/123Z" which are invalid name whereas "Lfoo/Foo.123Z;" (option 
c) may have higher chance be mapped to "foo.Foo.123Z" which is a valid 
binary name.

";" and "[" are already used for descriptor.  The remaining ones are "." 
and "/".

JDWP and JDI are examples of existing tools that obtain the type 
descriptor by calling JVM TI `GetClassSignature` and then trims the "L;" 
envelope and replace "/" with ".".    Option c produces "foo.Foo.123Z" 
as the resulting string which might make it harder

6. Throwing an exception (option a) may make existing libraries to catch 
issues very early on.  I see the consistency that John made about 
dual-use APIs that prints a human-readable but not resolvable 
descriptor.  I got convinced that option c and c' have the benefit over 
option a.

7. Existing tools or scripts that parse the descriptor string have to be 
updated in both option c and c' to properly handle hidden classes.  
Option c may just hide the problem which is bad if it's left unnoticed 
but happens in customer environments.

My only concern is the compatibility risk on existing agents that assume 
JVM TI `GetClassSignature` returns a valid type descriptor and use it to 
resolution.   Both option c and c' return an invalid descriptor string 
and so I consider the impact is about the same. JDI and JDWP have to be 
updated to work with either new form.   As John noted, option c' has the 
fail-fast properties that may help existing code to diagnose issues 
during migration.

That's my summary why I went with option c'.    The preference is 
"slightly".

Any other thought?

Mandy
[1] 
http://cr.openjdk.java.net/~mchung/valhalla/webrevs/hidden-classes/webrev.06-delta/


More information about the valhalla-dev mailing list