[nestmates] Name of a hidden class and stack trace

Mandy Chung mandy.chung at oracle.com
Thu Aug 29 23:16:22 UTC 2019


If a hidden class invokes a lambda, as the target class is a hidden
class whose name contains '/', it will need to be converted so that
the lambda proxy class will be in the same package "foo".  So
stack trace will look like something like this:

java.lang.Error: thrown from hidden class foo.Foo_0x0000000800b7a470
	at m1/foo.Foo/0x0000000800b7a470.toString(Foo.java:16)
	at m1/foo.Foo_0x0000000800b7a470$$Lambda$29/0x0000000800b7c040.apply(<Unknown>:1000001)
	at m1/foo.Foo/0x0000000800b7a470.test(Foo.java:11)

lambda proxy: foo.Foo_0x0000000800b7a470$$Lambda$29/0x0000000800b7c040
for:          foo.Foo/0x0000000800b7a470

One single '/' in both hidden class's names while the simple name
has one odd single character difference.  It's not too bad though
as the frames are hidden by default.  The alternative would use
a valid binary name but that requires existing tools to migrate.
Another thing I like '/' is that StackTraceElement::toString uses
'/' in separating classloader/module/classname and now /0x....
is shown to separate its id.

Mandy


On 8/29/19 11:42 AM, Brian Goetz wrote:
> This trick has worked well for us with anon classes, and there’s already plenty of code out there that does `name.contains(‘/‘)` to defend against it, so I see no reason to break from this convention.
>
>> On Aug 29, 2019, at 2:34 PM, Mandy Chung <mandy.chung at oracle.com> wrote:
>>
>> I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the nestmates branch (JDK-8171335).  Attached describes about hidden classes (thanks to Alex Buckley for the help) and description about nestmates/weak will come next.
>>
>> A hidden class cannot be named by other class.   Ideally a hidden class should  be nameless.  For troubleshooting and stack trace, a hidden class needs a name.   So the proposal has been:
>>
>> Class::getName returns a name for a hidden class and the name is unique in the runtime package namespace.  That is, there is no two Class objects with the same name in the same runtime package.
>>
>> Below shows the stack trace where a hidden class throws an exception.
>>
>> $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass foo/Foo.class
>> java.lang.Error: error
>>      at foo.Foo_/0x0000000800b79258.run(Foo.java:9)
>>      at DefineClass.main(DefineClass.java:18)
>>
>> The current impl includes `/` in the hidden class's name to disjoint from the ordinary class names
>> (same trick as VM anonymous class).
>>
>> Another class calls Class::forName with the hidden class's name which would fail since that's not a valid binary name.   If someone attempts to spin a class referencing this hidden class's name with replace('.', '/'), it may attempt to load a class named 'foo/Foo_/0x0000000800b79258'  and may succeed if such a class file exists and can be located by class loader.  This is no difference than today as one can spin a class file to any class names.
>>
>> Class::getName may return an invalid binary name if it's a hidden class.  It will impact existing code that expects the returned name is a valid binary name or use the name to perform class lookup.  I think the compatibility concern should not be high.
>>
>> Thought?
>>
>> Mandy
>>



More information about the valhalla-dev mailing list