Developer API docs
Sundararajan Athijegannathan
sundararajan.athijegannathan at oracle.com
Fri Oct 16 02:56:49 UTC 2015
Hi Tal Liron,
Sorry about missing reply for this email. I somehow remember replying
similar nashorn internal usage email.
It is difficult maintain all of jdk.nashorn.internal.* between versions.
Also, with security manager around, jdk.nashorn.internal.* are not
accessible without explicit 'package access' RuntimePermission. In
addition, with jdk9, nashorn module exports only jdk.nashorn.api.*
packages. i.e., even without any security manager, user code won't be
able to access nashorn internal implementation classes. It is possible
to use jdk.nashorn.api.scripting.JSObject to get constructors and create
objecs.
JSObject numberConstructor = (JSObject) engine.eval("Number");
JSObject numberObj = numberConstructor.newObject();
Is it not possible to work with these? Please check out latest 8u-dev
code. Mostly explicit wrap/unwrap won't be required from user's code.
Thanks,
-Sundar
On 10/15/2015 10:21 PM, Tal Liron wrote:
> Hey guys, nobody ever responded to my message...
>
> Do you really think that my usage of these internal Nashorn APIs is so
> unwarranted?
>
> I tried to prove that some useful libraries need to use Nashorn APIs
> that some of you insist should not be made public.
>
> On 07/06/2015 09:10 PM, Tal Liron wrote:
>> Hi Atilla (and Sundar and everyone else, really),
>>
>> You asked which Nashorn APIs I'm using that are not documented. I
>> will reply in full detail.
>>
>> For the BSON/JSON codecs, the most important thing is to access the
>> NativeBoolean, NativeNumber, NativeArray, ConsString, Undefined,
>> etc., classes. This allows the codecs to check for these classes
>> incoming, and also to easily create instances of them using their
>> constructor() static method.
>>
>> ScriptObject has no constructor(), so I use
>> Global.newEmptyInstance(). (By the way: NativeDate and NativeArray
>> name the method construct() instead of constructor(). I assume this
>> is a consistency mistake.)
>>
>> But I also need to access their data. This means get()/set() for
>> NativeScriptObject and NativeArray, getOwnKeys(), getArray() (which
>> means I need access to the ArrayData class), and also getTime() for
>> NativeData. NativeRegExp is a bit harder, but I use get("source"),
>> get("multiline"), etc.
>>
>> (In Rhino, some of these classes are actually private! This required
>> an awkward workaround: I do a string equality check on the classname.
>> That's neither efficient nor portable, though more "dynamic", I
>> guess. Also, for these classes I can use Context.newObject() to
>> create instances by JS name, for example "RegExp". Then I can do
>> ScriptableObject.callMethod() to access their internals. So, there
>> are workarounds to not being to able to access them.)
>>
>> ScriptObjectMirror is awkward. Though it's stable and documented, the
>> issue with unwrap() is that it needs a global. Documented, but of
>> course unclear what to do! For me, this actually means calling
>> Context.getGlobal(), which is not publicly documented. (Another issue
>> is that, of course, unwrap won't work for other globals. This has
>> created difficulties in some threaded environments in which multiple
>> globals are used intentionally. More on that below.)
>>
>> So much for BSON/JSON. The Scripturian implementation of Nashorn is
>> much more complex. As you may know, Scripturian is a rethinking of
>> and alternative to JSR-223, so it has to do much of the same work.
>>
>> Scripturian works by purposely creating different global instances
>> for each "execution context" (which *can* be a thread, but doesn't
>> have to be: it's an abstraction over, well, execution contexts). I
>> use Context.createGlobal(), and set it via Context.setGlobal().
>>
>> We then need to compile scripts in the Context, so I use
>> Source.sourceFor() and Context.compileScript(), which returns a
>> ScriptFunction, so I also need access to that. Compilations errors
>> are via Context.getErrorManager(), so I need access to ErrorManager.
>> To run the scripts, I use ScriptRuntime.apply(). A small fix I need
>> to add is that Nashorn's NativeArray does not support java.util.List,
>> so if an array is returned from apply(), I call NativeJava.to() to
>> get list access. Thats's just a bit friendlier for users of
>> Scripturian, who are otherwise agnostic about implementation specifics.
>>
>> There's an important issue here: remember, there might be many
>> different globals, but of course I want them all to use the same code
>> cache, which is stored in the Context. So, I use one singleton
>> Context and switch globals via Context.setGlobal(). To create a
>> Context, I also need access to Options. A limitation in Nashorn is
>> that I can't change stdout and stderr after I create the Context
>> (Scripturian allows different onces per ExecutionContext), so my
>> workaround is to use a custom Writer wrapper class that underneath
>> delegates to the correct "real" Writers (I use the same mechanism for
>> a few other Scripturian language engines, too).
>>
>> I grumbled here before that I have no programmatic access to the code
>> cache. Behind the scenes, ScriptFunction might retrieve from the
>> cache instead of being compiled. I can control the cache base
>> location via the "nashorn.persistent.code.cache" system property, but
>> it's unfortunate that I can't control the structure and naming the
>> way I can with other languages supported by Scripturian. In
>> particular, the problem is that it's a global property for the whole
>> JVM, whereas compilation and caching location is ideally controlled
>> per ExecutionContext in Scripturian. This makes Nashorn support in
>> Scripturian a bit more limited.
>>
>> Finally, for errors during execution, I use NashornException
>> (documented!) to extract specific information into Scripturian's more
>> generic ExecutionException.
>>
>> Small extras: I use Version.version() and
>> NashornScriptEngineFactory.getLanguageVersion() to get version data.
>>
>> I think that's everything! Of course, I also had to "reverse
>> engineer" much of this (=read a lot of code) and work around many
>> quirks (and big differences to Rhino's implementation) before
>> streamlining it down to just these few classes. (I tried to work
>> around the caching limitations, but gave up due to its complexity.
>> Also, I think some of the key classes I would need are private.) I
>> did my best not to delve to much into internals, but I hope I made it
>> clear to you that it would have been impossible to achieve all the
>> above goals without it.
>>
>> -Tal
>>
>> On 07/06/2015 04:18 AM, Attila Szegedi wrote:
>>> What APIs are you using, BTW? Just curious if I can suggest an
>>> alternative approach, or even consider if something you use should
>>> be publicly supported.
>>
>
More information about the nashorn-dev
mailing list