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