eobermuhlner / jshell-scriptengine

JShell script engine for Java (JSR-223 compatible)
MIT License
32 stars 8 forks source link

Class made in eval can be used normally in that eval but can only be used by reflection in later eval #5

Open benrayfield opened 3 years ago

benrayfield commented 3 years ago

System.out.println("java.version="+System.getProperty("java.version")); System.out.println("java.runtime.name="+System.getProperty("java.runtime.name")); ScriptEngine jshell = new JShellScriptEngine(); Bindings b = jshell.createBindings(); jshell.setBindings(b, ScriptContext.GLOBAL_SCOPE); jshell.setBindings(b, ScriptContext.ENGINE_SCOPE); long start = System.nanoTime(); jshell.eval("long kk = 0L; for(int i=0; i<100000000; i++) kk += i; System.out.println(\"kk=\"+kk); 20;"); double duration = (System.nanoTime()-start)*1e-9; System.out.println("duration="+duration+" loopBodiesPerSec="+(1e8/duration)); Object xy = jshell.eval("class PairXY{ public final int x, y; public PairXY(int x, int y){ this.x = x; this.y=y; } public Object theT(){ return 9.87; } } Class PairXYClass = PairXY.class;"); System.out.println("PairXYClass: "+jshell.eval("PairXYClass")); System.out.println("xy = "+xy); System.out.println("xy.getClass() = "+xy.getClass()); Object mmB = jshell.eval("Object mmB = PairXYClass.getConstructor(int.class,int.class).newInstance(55,66);"); System.out.println("mmB = "+mmB); System.out.println("mmB.getClass() = "+mmB.getClass()); double calledTheTByReflection = (Double) mmB.getClass().getMethod("theT").invoke(mmB); System.out.println("calledTheTByReflection = "+calledTheTByReflection);

Outputs this...

java.version=11.0.2 java.runtime.name=OpenJDK Runtime Environment kk=4999999950000000 duration=0.523169 loopBodiesPerSec=1.9114282382939357E8 PairXYClass: class REPL.$JShell$3$PairXY xy = class REPL.$JShell$3$PairXY xy.getClass() = class java.lang.Class mmB = REPL.$JShell$3$PairXY@55b62629 mmB.getClass() = class REPL.$JShell$3$PairXY calledTheTByReflection = 9.87

If "new PairXY(2,3)" is in the first eval, it works, but not if its in the second later evals. So I put its Class object in a jshell var so the later evals could see it and use by reflection, and it works, as you see theT called which returns 9.87.

Is there an easier way to keep classes across evals?