On 10/19/20 11:44 AM, Remi Forax wrote:
------------------------------------------------------------------------
Hi Attila,
* for now, I disabled anonymous code loading. It’s a funny
one. Nashorn has a
feature called “anonymous code loading” that it uses for
somewhat
lighter-weight loading of code as it compiles JavaScript
functions one-by-one
into bytecode classes. Unfortunately, it uses
Unsafe.defineAnonymousClass for
that, and outside of JDK it can’t access Unsafe. So I
switched to a new API,
luckily available from Java 15,
MethodHandles.Lookup.defineHiddenClass. It
seems to work as it should, except with it, eval’d
expressions no longer report
“<eval>” as their script name and anonymous functions no
longer report
“<anonymous>” but rather their callers names, script
names, and line numbers
are reported. It’s quite maddening, and if I can’t get to
the bottom of it in
reasonable amount of time.
I also had converted to use `Lookup::defineHiddenClass` but I missed
this stack trace issue.
http://hg.openjdk.java.net/valhalla/valhalla/file/fb5c34c883b5/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java#l321
How does the engine walk the stack frame and report "<eval>" as their
script name and anonymous functions? I wonder if StackWalker can help
here (as Remi mentions).
A hidden class is well, hidden, so it doesn't appear by
default in the stack trace (You have a special configuation of
the StackWalker that shows the hidden classes).
With an anonymous class, you can use the annotation @Hidden or
not but with a hidden class, you have no choice, a hidden
class is always hidden.
Thanks for chiming in, Remi! I just came back from an evening
walk, and around halfway into it I actually had this lightbulb go
on thinking “y’know, this feels like the the stack frames are hidden…”
Also, you can still use Unsafe.defineAnonymous class with Java
15, but using sun.misc.Unsafe and not jdk.internal.misc.Unsafe.
But it's a short term solution given that
sun.misc.Unsafe.defineAnonymous is now deprecated.
I gave it a brief try, but the compiler complained that the
package sun.misc is not visible. And anyway I was hoping for using
a supported public API :-) I might give it _another_ try. I’m not
sure what else do I need to do, but I hope it can be done without
users needing to screw around with JVM flags such as --add-exports
etc.
you may not be able to access it directly, but you can still write
Class<?> unsafe = Class.forName("sun.misc.unsafe");
jdk.unsupported exports and opens `sun.misc` and so `sun.misc.Unsafe`
should be accessible as in JDK 8.
also, if you are modular, you need to requires jdk.unsupported,
sun.misc.Unsafe is not in java.base.
That might be the cause of the issue.
I’ll just keep anonymous code loading switched off
for initial release. There’s not many drawbacks to it,
maybe a bit higher
memory utilization if you don’t use optimistic types. With
optimistic types, it
would preclude obsolete code versions from clearing up
from memory when
functions are repeatedly recompiled until the whole script
gets unloaded.
I've added Mandy in CC, given you are not the first one to ask
for a "visible" hidden class, so maybe, the ClassOption could
be extended to had a VISIBLE option ?
That’d be awesome! By the way, Mandy, it is already awesome that
we have Lookup.defineHiddenClass !
yep, +1
Thank you.
My apology that I haven't had time to consider JDK-8212620 more. I
still think VISIBLE option is option while it is relevant to JDK-8212620
as well. It's better to consider them together.
As I ask above, would StackWalker with SHOW_HIDDEN_FRAMES option help to
find the stack frame with hidden class?
Mandy