зеркало из https://github.com/mozilla/pjs.git
Implementing bug 281247: JDK compatibility is implemented through VMBridge class and its subclasses to avoid excessive reflection usage.
This commit is contained in:
Родитель
ebd1bd1951
Коммит
bb1ee0458d
|
@ -274,6 +274,24 @@ public class Context
|
|||
optimizationLevel = codegenClass != null ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current Context.
|
||||
*
|
||||
* The current Context is per-thread; this method looks up
|
||||
* the Context associated with the current thread. <p>
|
||||
*
|
||||
* @return the Context associated with the current thread, or
|
||||
* null if no context is associated with the current
|
||||
* thread.
|
||||
* @see org.mozilla.javascript.Context#enter()
|
||||
* @see org.mozilla.javascript.Context#exit()
|
||||
*/
|
||||
public static Context getCurrentContext()
|
||||
{
|
||||
Object helper = VMBridge.instance.getThreadContextHelper();
|
||||
return VMBridge.instance.getContext(helper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a context associated with the current thread, creating
|
||||
* one if need be.
|
||||
|
@ -339,14 +357,8 @@ public class Context
|
|||
*/
|
||||
public static Context enter(Context cx)
|
||||
{
|
||||
Object[] storage = getThreadContextStorage();
|
||||
Context old;
|
||||
if (storage != null) {
|
||||
old = (Context)storage[0];
|
||||
} else {
|
||||
old = getCurrentContext_jdk11();
|
||||
}
|
||||
|
||||
Object helper = VMBridge.instance.getThreadContextHelper();
|
||||
Context old = VMBridge.instance.getContext(helper);
|
||||
if (old != null) {
|
||||
if (cx != null && cx != old && cx.enterCount != 0) {
|
||||
// The suplied context must be the context for
|
||||
|
@ -378,11 +390,7 @@ public class Context
|
|||
}
|
||||
|
||||
if (old == null) {
|
||||
if (storage != null) {
|
||||
storage[0] = cx;
|
||||
} else {
|
||||
setThreadContext_jdk11(cx);
|
||||
}
|
||||
VMBridge.instance.setContext(helper, cx);
|
||||
}
|
||||
++cx.enterCount;
|
||||
|
||||
|
@ -406,13 +414,8 @@ public class Context
|
|||
*/
|
||||
public static void exit()
|
||||
{
|
||||
Object[] storage = getThreadContextStorage();
|
||||
Context cx;
|
||||
if (storage != null) {
|
||||
cx = (Context)storage[0];
|
||||
} else {
|
||||
cx = getCurrentContext_jdk11();
|
||||
}
|
||||
Object helper = VMBridge.instance.getThreadContextHelper();
|
||||
Context cx = VMBridge.instance.getContext(helper);
|
||||
if (cx == null) {
|
||||
throw new IllegalStateException(
|
||||
"Calling Context.exit without previous Context.enter");
|
||||
|
@ -426,14 +429,7 @@ public class Context
|
|||
if (cx.sealed) onSealedMutation();
|
||||
--cx.enterCount;
|
||||
if (cx.enterCount == 0) {
|
||||
if (storage != null) {
|
||||
storage[0] = null;
|
||||
} else {
|
||||
setThreadContext_jdk11(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (cx.enterCount == 0) {
|
||||
VMBridge.instance.setContext(helper, null);
|
||||
ContextFactory.getGlobal().onContextReleased(cx);
|
||||
}
|
||||
}
|
||||
|
@ -478,33 +474,31 @@ public class Context
|
|||
factory = ContextFactory.getGlobal();
|
||||
}
|
||||
|
||||
Object[] storage = getThreadContextStorage();
|
||||
Context cx;
|
||||
if (storage != null) {
|
||||
cx = (Context)storage[0];
|
||||
} else {
|
||||
cx = getCurrentContext_jdk11();
|
||||
}
|
||||
|
||||
Object helper = VMBridge.instance.getThreadContextHelper();
|
||||
Context cx = VMBridge.instance.getContext(helper);
|
||||
if (cx != null) {
|
||||
Object result;
|
||||
if (cx.factory != null) {
|
||||
return callable.call(cx, scope, thisObj, args);
|
||||
result = callable.call(cx, scope, thisObj, args);
|
||||
} else {
|
||||
// Context was associated with the thread via Context.enter
|
||||
// Context was associated with the thread via Context.enter,
|
||||
// set factory to make Context.enter/exit to be no-op
|
||||
// during call
|
||||
cx.factory = factory;
|
||||
try {
|
||||
return callable.call(cx, scope, thisObj, args);
|
||||
result = callable.call(cx, scope, thisObj, args);
|
||||
} finally {
|
||||
cx.factory = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
cx = prepareNewContext(factory, storage);
|
||||
cx = prepareNewContext(factory, helper);
|
||||
try {
|
||||
return callable.call(cx, scope, thisObj, args);
|
||||
} finally {
|
||||
releaseContext(storage, cx);
|
||||
releaseContext(helper, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,13 +507,8 @@ public class Context
|
|||
*/
|
||||
static Object call(ContextFactory factory, ContextAction action)
|
||||
{
|
||||
Object[] storage = getThreadContextStorage();
|
||||
Context cx;
|
||||
if (storage != null) {
|
||||
cx = (Context)storage[0];
|
||||
} else {
|
||||
cx = getCurrentContext_jdk11();
|
||||
}
|
||||
Object helper = VMBridge.instance.getThreadContextHelper();
|
||||
Context cx = VMBridge.instance.getContext(helper);
|
||||
|
||||
if (cx != null) {
|
||||
if (cx.factory != null) {
|
||||
|
@ -534,16 +523,16 @@ public class Context
|
|||
}
|
||||
}
|
||||
|
||||
cx = prepareNewContext(factory, storage);
|
||||
cx = prepareNewContext(factory, helper);
|
||||
try {
|
||||
return action.run(cx);
|
||||
} finally {
|
||||
releaseContext(storage, cx);
|
||||
releaseContext(helper, cx);
|
||||
}
|
||||
}
|
||||
|
||||
private static Context prepareNewContext(ContextFactory factory,
|
||||
Object[] storage)
|
||||
Object contextHelper)
|
||||
{
|
||||
Context cx = factory.makeContext();
|
||||
if (cx.factory != null || cx.enterCount != 0) {
|
||||
|
@ -554,22 +543,13 @@ public class Context
|
|||
if (factory.isSealed() && !cx.isSealed()) {
|
||||
cx.seal(null);
|
||||
}
|
||||
if (storage != null) {
|
||||
storage[0] = cx;
|
||||
} else {
|
||||
setThreadContext_jdk11(cx);
|
||||
}
|
||||
|
||||
VMBridge.instance.setContext(contextHelper, cx);
|
||||
return cx;
|
||||
}
|
||||
|
||||
private static void releaseContext(Object[] storage, Context cx)
|
||||
private static void releaseContext(Object contextHelper, Context cx)
|
||||
{
|
||||
if (storage != null) {
|
||||
storage[0] = null;
|
||||
} else {
|
||||
setThreadContext_jdk11(null);
|
||||
}
|
||||
VMBridge.instance.setContext(contextHelper, null);
|
||||
try {
|
||||
cx.factory.onContextReleased(cx);
|
||||
} finally {
|
||||
|
@ -616,60 +596,6 @@ public class Context
|
|||
ContextFactory.getGlobal().addListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current Context.
|
||||
*
|
||||
* The current Context is per-thread; this method looks up
|
||||
* the Context associated with the current thread. <p>
|
||||
*
|
||||
* @return the Context associated with the current thread, or
|
||||
* null if no context is associated with the current
|
||||
* thread.
|
||||
* @see org.mozilla.javascript.Context#enter
|
||||
* @see org.mozilla.javascript.Context#exit
|
||||
*/
|
||||
public static Context getCurrentContext()
|
||||
{
|
||||
Object[] storage = getThreadContextStorage();
|
||||
if (storage != null) {
|
||||
return (Context)storage[0];
|
||||
}
|
||||
return getCurrentContext_jdk11();
|
||||
}
|
||||
|
||||
private static Object[] getThreadContextStorage()
|
||||
{
|
||||
if (threadLocalCx != null) {
|
||||
try {
|
||||
Object[] storage
|
||||
= (Object[])threadLocalGet.invoke(threadLocalCx, null);
|
||||
if (storage == null) {
|
||||
storage = new Object[1];
|
||||
threadLocalSet.invoke(threadLocalCx,
|
||||
new Object[] { storage });
|
||||
}
|
||||
return storage;
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Context getCurrentContext_jdk11()
|
||||
{
|
||||
Thread t = Thread.currentThread();
|
||||
return (Context) threadContexts.get(t);
|
||||
}
|
||||
|
||||
private static void setThreadContext_jdk11(Context cx)
|
||||
{
|
||||
Thread t = Thread.currentThread();
|
||||
if (cx != null) {
|
||||
threadContexts.put(t, cx);
|
||||
} else {
|
||||
threadContexts.remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link ContextFactory} instance used to create this Context
|
||||
* or the result of {@link ContextFactory#getGlobal()} if no factory
|
||||
|
@ -2173,21 +2099,15 @@ public class Context
|
|||
// in any case or JVM class loading is severely broken
|
||||
Class cxClass = this.getClass();
|
||||
ClassLoader loader = cxClass.getClassLoader();
|
||||
if (method_getContextClassLoader != null) {
|
||||
Thread thread = Thread.currentThread();
|
||||
ClassLoader threadLoader = null;
|
||||
try {
|
||||
threadLoader = (ClassLoader)method_getContextClassLoader.
|
||||
invoke(thread, ScriptRuntime.emptyArgs);
|
||||
} catch (Exception ex) { }
|
||||
if (threadLoader != null && threadLoader != loader) {
|
||||
if (testIfCanUseLoader(threadLoader, cxClass)) {
|
||||
// Thread.getContextClassLoader is not cached since
|
||||
// its caching prevents it from GC which may lead to
|
||||
// a memory leak and hides updates to
|
||||
// Thread.getContextClassLoader
|
||||
return threadLoader;
|
||||
}
|
||||
ClassLoader threadLoader
|
||||
= VMBridge.instance.getCurrentThreadClassLoader();
|
||||
if (threadLoader != null && threadLoader != loader) {
|
||||
if (testIfCanUseLoader(threadLoader, cxClass)) {
|
||||
// Thread.getContextClassLoader is not cached since
|
||||
// its caching prevents it from GC which may lead to
|
||||
// a memory leak and hides updates to
|
||||
// Thread.getContextClassLoader
|
||||
return threadLoader;
|
||||
}
|
||||
}
|
||||
applicationClassLoader = loader;
|
||||
|
@ -2469,41 +2389,6 @@ public class Context
|
|||
activationNames.remove(name);
|
||||
}
|
||||
|
||||
private static Hashtable threadContexts = new Hashtable(11);
|
||||
private static Object threadLocalCx;
|
||||
private static Method threadLocalGet;
|
||||
private static Method threadLocalSet;
|
||||
|
||||
static {
|
||||
Class cl = Kit.classOrNull("java.lang.ThreadLocal");
|
||||
if (cl != null) {
|
||||
try {
|
||||
threadLocalGet = cl.getMethod("get", null);
|
||||
threadLocalSet = cl.getMethod("set",
|
||||
new Class[] { ScriptRuntime.ObjectClass });
|
||||
threadLocalCx = cl.newInstance();
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
}
|
||||
|
||||
// We'd like to use "Thread.getContextClassLoader", but
|
||||
// that's only available on Java2.
|
||||
private static Method method_getContextClassLoader;
|
||||
|
||||
static {
|
||||
// Don't use "Thread.class": that performs the lookup
|
||||
// in the class initializer, which doesn't allow us to
|
||||
// catch possible security exceptions.
|
||||
Class threadClass = Kit.classOrNull("java.lang.Thread");
|
||||
if (threadClass != null) {
|
||||
try {
|
||||
method_getContextClassLoader =
|
||||
threadClass.getDeclaredMethod("getContextClassLoader",
|
||||
new Class[0]);
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
}
|
||||
|
||||
private static String implementationVersion;
|
||||
|
||||
private ContextFactory factory;
|
||||
|
|
|
@ -145,7 +145,7 @@ final class MemberBox implements Serializable
|
|||
memberObject = accessible;
|
||||
method = accessible;
|
||||
} else {
|
||||
if (!tryToMakeAccessible(method)) {
|
||||
if (!VMBridge.instance.tryToMakeAccessible(method)) {
|
||||
throw Context.throwAsScriptRuntimeEx(ex);
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ final class MemberBox implements Serializable
|
|||
try {
|
||||
return ctor.newInstance(args);
|
||||
} catch (IllegalAccessException ex) {
|
||||
if (!tryToMakeAccessible(ctor)) {
|
||||
if (!VMBridge.instance.tryToMakeAccessible(ctor)) {
|
||||
throw Context.throwAsScriptRuntimeEx(ex);
|
||||
}
|
||||
}
|
||||
|
@ -218,26 +218,6 @@ final class MemberBox implements Serializable
|
|||
return null;
|
||||
}
|
||||
|
||||
private static boolean tryToMakeAccessible(Member member)
|
||||
{
|
||||
/**
|
||||
* Due to a bug in Sun's VM, public methods in private
|
||||
* classes are not accessible by default (Sun Bug #4071593).
|
||||
* We have to explicitly set the method accessible
|
||||
* via method.setAccessible(true) but we have to use
|
||||
* reflection because the setAccessible() in Method is
|
||||
* not available under jdk 1.1.
|
||||
*/
|
||||
if (method_setAccessible != null) {
|
||||
try {
|
||||
Object[] args_wrapper = { Boolean.TRUE };
|
||||
method_setAccessible.invoke(member, args_wrapper);
|
||||
return true;
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
|
@ -367,17 +347,5 @@ final class MemberBox implements Serializable
|
|||
|
||||
private transient Member memberObject;
|
||||
transient Class[] argTypes;
|
||||
|
||||
private static Method method_setAccessible;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class MethodClass = Class.forName("java.lang.reflect.Method");
|
||||
method_setAccessible = MethodClass.getMethod(
|
||||
"setAccessible", new Class[] { Boolean.TYPE });
|
||||
} catch (Exception ex) {
|
||||
// Assume any exceptions means the method does not exist.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,18 +89,19 @@ public class ScriptRuntime {
|
|||
ObjectClass = Kit.classOrNull("java.lang.Object"),
|
||||
ShortClass = Kit.classOrNull("java.lang.Short"),
|
||||
StringClass = Kit.classOrNull("java.lang.String"),
|
||||
|
||||
SerializableClass = Kit.classOrNull("java.io.Serializable"),
|
||||
|
||||
DateClass = Kit.classOrNull("java.util.Date");
|
||||
|
||||
public final static Class
|
||||
ContextClass = Kit.classOrNull("org.mozilla.javascript.Context"),
|
||||
ContextFactoryClass = Kit.classOrNull("org.mozilla.javascript.ContextFactory"),
|
||||
FunctionClass = Kit.classOrNull("org.mozilla.javascript.Function"),
|
||||
ScriptableClass = Kit.classOrNull("org.mozilla.javascript.Scriptable"),
|
||||
ScriptableObjectClass = Kit.classOrNull("org.mozilla.javascript.ScriptableObject"),
|
||||
UndefinedClass = Kit.classOrNull("org.mozilla.javascript.Undefined");
|
||||
ContextClass
|
||||
= Kit.classOrNull("org.mozilla.javascript.Context"),
|
||||
ContextFactoryClass
|
||||
= Kit.classOrNull("org.mozilla.javascript.ContextFactory"),
|
||||
FunctionClass
|
||||
= Kit.classOrNull("org.mozilla.javascript.Function"),
|
||||
ScriptableClass
|
||||
= Kit.classOrNull("org.mozilla.javascript.Scriptable"),
|
||||
ScriptableObjectClass
|
||||
= Kit.classOrNull("org.mozilla.javascript.ScriptableObject");
|
||||
|
||||
private static final String
|
||||
XML_INIT_CLASS = "org.mozilla.javascript.xmlimpl.XMLLibImpl";
|
||||
|
@ -672,7 +673,7 @@ public class ScriptRuntime {
|
|||
return "[object " + obj.getClassName() + ']';
|
||||
}
|
||||
|
||||
public static String toString(Object[] args, int index)
|
||||
public static String toString(Object[] args, int index)
|
||||
{
|
||||
return (index < args.length) ? toString(args[index]) : "undefined";
|
||||
}
|
||||
|
@ -2419,7 +2420,7 @@ public class ScriptRuntime {
|
|||
}
|
||||
}
|
||||
|
||||
private static Object toPrimitive(Object val)
|
||||
private static Object toPrimitive(Object val)
|
||||
{
|
||||
if (!(val instanceof Scriptable)) {
|
||||
return val;
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Igor Bukanov, igor@mir2.org
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
public abstract class VMBridge
|
||||
{
|
||||
|
||||
static final VMBridge instance = makeInstance();
|
||||
|
||||
private static VMBridge makeInstance()
|
||||
{
|
||||
for (int i = 0; i != 3; ++i) {
|
||||
String className;
|
||||
if (i == 0) {
|
||||
className = "org.mozilla.javascript.VMBridge_custom";
|
||||
} else if (i == 1) {
|
||||
className = "org.mozilla.javascript.jdk13.VMBridge_jdk13";
|
||||
} else {
|
||||
className = "org.mozilla.javascript.jdk11.VMBridge_jdk11";
|
||||
}
|
||||
Class cl = Kit.classOrNull(className);
|
||||
if (cl != null) {
|
||||
VMBridge bridge = (VMBridge)Kit.newInstanceOrNull(cl);
|
||||
if (bridge != null) {
|
||||
return bridge;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to create VMBridge instance");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a helper object to optimize {@link Context} access.
|
||||
* <p>
|
||||
* The runtime will pass the resulting helper object to the subsequent
|
||||
* calls to {@link #getContext(Object contextHelper)} and
|
||||
* {@link #setContext(Object contextHelper, Context cx)} methods.
|
||||
* In this way the implementation can use the helper to cache
|
||||
* information about current thread to make {@link Context} access faster.
|
||||
*/
|
||||
protected abstract Object getThreadContextHelper();
|
||||
|
||||
/**
|
||||
* Get {@link Context} instance associated with the current thread
|
||||
* or null if none.
|
||||
*
|
||||
* @param contextHelper The result of {@link getThreadContextHelper()}
|
||||
* called from the current thread.
|
||||
*/
|
||||
protected abstract Context getContext(Object contextHelper);
|
||||
|
||||
/**
|
||||
* Associate {@link Context} instance with the current thread or remove
|
||||
* the current association if <tt>cx</tt> is null.
|
||||
*
|
||||
* @param contextHelper The result of {@link getThreadContextHelper()}
|
||||
* called from the current thread.
|
||||
*/
|
||||
protected abstract void setContext(Object contextHelper, Context cx);
|
||||
|
||||
/**
|
||||
* Return the ClassLoader instance associated with the current thread.
|
||||
*/
|
||||
protected abstract ClassLoader getCurrentThreadClassLoader();
|
||||
|
||||
/**
|
||||
* In many JVMSs, public methods in private
|
||||
* classes are not accessible by default (Sun Bug #4071593).
|
||||
* VMBridge instance should try to workaround that via, for example,
|
||||
* calling method.setAccessible(true) when it is available.
|
||||
* The implementation is responsible to catch all possible exceptions
|
||||
* like SecurityException if the workaround is not available.
|
||||
*
|
||||
* @return true if it was possible to make method accessible
|
||||
* or false otherwise.
|
||||
*/
|
||||
protected abstract boolean tryToMakeAccessible(Object accessibleObject);
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Igor Bukanov, igor@mir2.org
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript.jdk11;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
public class VMBridge_jdk11 extends VMBridge
|
||||
{
|
||||
private Hashtable threadsWithContext = new Hashtable();
|
||||
|
||||
protected Object getThreadContextHelper()
|
||||
{
|
||||
return Thread.currentThread();
|
||||
}
|
||||
|
||||
protected Context getContext(Object contextHelper)
|
||||
{
|
||||
Thread t = (Thread)contextHelper;
|
||||
return (Context)threadsWithContext.get(t);
|
||||
}
|
||||
|
||||
protected void setContext(Object contextHelper, Context cx)
|
||||
{
|
||||
Thread t = (Thread)contextHelper;
|
||||
if (cx == null) {
|
||||
// Allow to garbage collect thread reference
|
||||
threadsWithContext.remove(t);
|
||||
} else {
|
||||
threadsWithContext.put(t, cx);
|
||||
}
|
||||
}
|
||||
|
||||
protected ClassLoader getCurrentThreadClassLoader()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean tryToMakeAccessible(Object accessibleObject)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Igor Bukanov, igor@mir2.org
|
||||
* Attila Szegedi, szegedia@freemail.hu
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript.jdk13;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
public class VMBridge_jdk13 extends VMBridge
|
||||
{
|
||||
private ThreadLocal contextLocal = new ThreadLocal();
|
||||
|
||||
protected Object getThreadContextHelper()
|
||||
{
|
||||
// To make subsequent batch calls to getContext/setContext faster
|
||||
// associate permanently one element array with contextLocal
|
||||
// so getContext/setContext would need just to read/write the first
|
||||
// array element.
|
||||
// Note that it is necessary to use Object[], not Context[] to allow
|
||||
// garbage collection of Rhino classes. For details see comments
|
||||
// by Attila Szegedi in
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=281067#c5
|
||||
|
||||
Object[] storage = (Object[])contextLocal.get();
|
||||
if (storage == null) {
|
||||
storage = new Object[1];
|
||||
contextLocal.set(storage);
|
||||
}
|
||||
return storage;
|
||||
}
|
||||
|
||||
protected Context getContext(Object contextHelper)
|
||||
{
|
||||
Object[] storage = (Object[])contextHelper;
|
||||
return (Context)storage[0];
|
||||
}
|
||||
|
||||
protected void setContext(Object contextHelper, Context cx)
|
||||
{
|
||||
Object[] storage = (Object[])contextHelper;
|
||||
storage[0] = cx;
|
||||
}
|
||||
|
||||
protected ClassLoader getCurrentThreadClassLoader()
|
||||
{
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
protected boolean tryToMakeAccessible(Object accessibleObject)
|
||||
{
|
||||
if (!(accessibleObject instanceof AccessibleObject)) {
|
||||
return false;
|
||||
}
|
||||
AccessibleObject accessible = (AccessibleObject)accessibleObject;
|
||||
if (accessible.isAccessible()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
accessible.setAccessible(true);
|
||||
} catch (Exception ex) { }
|
||||
|
||||
return accessible.isAccessible();
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче