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