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

Mandy Chung mandy.chung at oracle.com
Mon Apr 13 20:18:45 UTC 2020



On 4/13/20 12:09 PM, Mandy Chung wrote:
>
>
> 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?

Another consideration:
    The name of an array class with a hidden class as its element type.

Option c -
    `Class::getName` returns "[Lfoo.Foo/123Z;" and 
`Class::descriptorString` returns "[Lfoo/Foo.123Z;"

The name of array class for `HC[]` is "[" + "L" + <HC's name> + ";"
The descriptor of array class for `HC[]` is "[" + <HC's descriptor>

Option c' -  what should `Class::getName` return?
(i) `Class::getName` "[Lfoo.Foo/123Z;" and `Class::descriptorString` 
returns "[Lfoo/Foo;/123Z"

The name of array class for `HC[]` is "[" + "L" + <HC's name> + ";"
The descriptor of array class for `HC[]` is "[" + <HC's descriptor>

It is not trivially obvious to tell from the resulting name and 
descriptor string represent the same array class of HC[].
(ii) `Class::getName` "[Lfoo.Foo;/123Z" and `Class::descriptorString` 
returns "[Lfoo/Foo;/123Z"

"foo.Foo/123Z" is HC's class name and "[Lfoo.Foo;/123Z" isn't quite 
right to be the name of array class of HC.   (i) is less awful.

Mandy

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



More information about the valhalla-dev mailing list