--- old/src/jdk.hotspot.agent/share/classes/module-info.java 2019-04-19 21:53:08.205060476 +0900 +++ new/src/jdk.hotspot.agent/share/classes/module-info.java 2019-04-19 21:53:07.935057749 +0900 @@ -43,8 +43,11 @@ requires java.desktop; requires java.rmi; requires java.scripting; + requires jdk.dynalink; + requires transitive jdk.scripting.nashorn; // RMI needs to serialize types in this package exports sun.jvm.hotspot.debugger.remote to java.rmi; + exports sun.jvm.hotspot.utilities.soql.wrapper; } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js 2019-04-19 21:53:08.742065899 +0900 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js 2019-04-19 21:53:08.477063223 +0900 @@ -29,6 +29,11 @@ // to avoid global namespace pollution var sapkg = new Object(); +var WrapperClass = Java.type('sun.jvm.hotspot.utilities.soql.wrapper.JSObjectClassWrapper'); +function SAType(clazz) { + return new WrapperClass(clazz); +} + sapkg.hotspot = Packages.sun.jvm.hotspot; sapkg.asm = sapkg.hotspot.asm; sapkg.c1 = sapkg.hotspot.c1; @@ -51,7 +56,7 @@ // SA singletons are kept in 'sa' object var sa = new Object(); -sa.vm = sapkg.runtime.VM.getVM(); +sa.vm = SAType(sapkg.runtime.VM).getVM(); sa.dbg = sa.vm.getDebugger(); sa.cdbg = sa.dbg.CDebugger; sa.heap = sa.vm.universe.heap(); --- /dev/null 2019-04-19 21:08:13.305241400 +0900 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/wrapper/JSObjectClassWrapper.java 2019-04-19 21:53:08.993068433 +0900 @@ -0,0 +1,32 @@ +package sun.jvm.hotspot.utilities.soql.wrapper; + +import java.util.Arrays; +import jdk.dynalink.beans.StaticClass; +import jdk.nashorn.api.scripting.AbstractJSObject; + + +public class JSObjectClassWrapper extends AbstractJSObject{ + + private final Class clazz; + + public JSObjectClassWrapper(Object clazz){ + StaticClass staticClass = (StaticClass)clazz; + this.clazz = staticClass.getRepresentedClass(); + } + + @Override + public Object getMember(String name){ + var method = Arrays.stream(clazz.getMethods()) + .filter(m -> m.getName().equals(name)) + .findFirst() + .get(); + return new JSObjectMethodWrapper(clazz, method); + } + + @Override + public boolean hasMember(String name){ + return Arrays.stream(clazz.getMethods()) + .anyMatch(m -> m.getName().equals(name)); + } + +} --- /dev/null 2019-04-19 21:08:13.305241400 +0900 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/wrapper/JSObjectInstanceWrapper.java 2019-04-19 21:53:09.530073856 +0900 @@ -0,0 +1,34 @@ +package sun.jvm.hotspot.utilities.soql.wrapper; + +import java.lang.reflect.Method; +import java.util.Arrays; +import jdk.nashorn.api.scripting.AbstractJSObject; + + +public class JSObjectInstanceWrapper extends AbstractJSObject{ + + private final Object thisObj; + + private final Method[] methods; + + public JSObjectInstanceWrapper(Object thisObj){ + this.thisObj = thisObj; + this.methods = thisObj.getClass().getMethods(); + } + + @Override + public Object getMember(String name){ + var method = Arrays.stream(methods) + .filter(m -> m.getName().equals(name)) + .findFirst() + .get(); + return new JSObjectMethodWrapper(thisObj, method); + } + + @Override + public boolean hasMember(String name){ + return Arrays.stream(methods) + .anyMatch(m -> m.getName().equals(name)); + } + +} --- /dev/null 2019-04-19 21:08:13.305241400 +0900 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/wrapper/JSObjectMethodWrapper.java 2019-04-19 21:53:10.072079329 +0900 @@ -0,0 +1,40 @@ +package sun.jvm.hotspot.utilities.soql.wrapper; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import jdk.nashorn.api.scripting.AbstractJSObject; + + +public class JSObjectMethodWrapper extends AbstractJSObject{ + + private final Object receiver; + + private final Method method; + + public JSObjectMethodWrapper(Object receiver, Method method){ + this.receiver = receiver; + this.method = method; + } + + /** + * Return result of this method object. + */ + @Override + public Object call(Object thiz, Object... args){ + Object result; + + try{ + result = method.invoke(receiver, args); + } catch(IllegalAccessException | InvocationTargetException e){ + throw new RuntimeException(e); + } + + return new JSObjectInstanceWrapper(result); + } + + @Override + public boolean isFunction(){ + return true; + } + +}