Информация об изменениях

Сообщение Re: вопрос по reflection от 07.11.2018 8:08

Изменено 07.11.2018 8:09 vsb

Re: вопрос по reflection
Вариант 1 (для выражений):

        var jShell = JShell.create();
        jShell.eval("String k1, k2;");
        jShell.eval("k1 = \"test\"; k2 = \"tset\";");
        var k1 = jShell.variables().filter(v -> v.name().equals("k1")).findAny().get();
        System.out.println(jShell.varValue(k1));


Вариант 2, требуе org.patrodyne:patrodyne-scripting-java:1.0.0

        var scriptEngineManager = new ScriptEngineManager();
        var scriptEngine = scriptEngineManager.getEngineByName("Java");
        var evalString = "k1 = \"test\"; k2 = \"tset\";";
        scriptEngine.eval()
        var evalClass = (Class<?>) scriptEngine.eval("" +
                "class Example {" +
                "    String k1, k2;" +
                "    Example() {" +
                "    }" +
                "    void run() {" +
                "        " + evalString + "" +
                "    }" +
                "}");
        var evalCtor = evalClass.getDeclaredConstructor();
        evalCtor.setAccessible(true);
        var evalObj = evalCtor.newInstance();
        Method evalRunMethod = evalClass.getDeclaredMethod("run");
        evalRunMethod.setAccessible(true);
        evalRunMethod.invoke(evalObj);
        Field evalK1Field = evalClass.getDeclaredField("k1");
        evalK1Field.setAccessible(true);
        var k1 = evalK1Field.get(evalObj);
        System.out.println(k1);


Вариант 3 (то, что ты описал, но без работы с диском, требует com.google.jimfs:jimfs:1.1):


        var javaCompiler = ToolProvider.getSystemJavaCompiler();
        var fileManager = javaCompiler.getStandardFileManager(null, ENGLISH, UTF_8);
        var fileSystem = Jimfs.newFileSystem(Configuration.unix());
        var evalString = "k1 = \"test\"; k2 = \"tset\";";
        Files.writeString(fileSystem.getPath("/Example.java"), "" +
                "public class Example implements Runnable {" +
                "    public String k1, k2;" +
                "    public void run() {" +
                "        " + evalString + "" +
                "    }" +
                "}");
        var sources = fileManager.getJavaFileObjects(fileSystem.getPath("/Example.java"));
        javaCompiler.getTask(null, fileManager, null, null, null, sources).call();
        var bytecode = Files.readAllBytes(fileSystem.getPath("/Example.class"));
        var classLoader = new ClassLoader() {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                if (name.equals("Example")) {
                    return defineClass(name, bytecode, 0, bytecode.length);
                }
                return super.findClass(name);
            }
        };
        var exampleClass = classLoader.findClass("Example");
        var exampleObj = (Runnable) exampleClass.getConstructor().newInstance();
        exampleObj.run();
        System.out.println(exampleClass.getField("k1").get(exampleObj));


Эти примеры из этой темы.
Re: вопрос по reflection
Вариант 1 (для выражений):

        var jShell = JShell.create();
        jShell.eval("String k1, k2;");
        jShell.eval("k1 = \"test\"; k2 = \"tset\";");
        var k1 = jShell.variables().filter(v -> v.name().equals("k1")).findAny().get();
        System.out.println(jShell.varValue(k1));


Вариант 2 (требует org.patrodyne:patrodyne-scripting-java:1.0.0):

        var scriptEngineManager = new ScriptEngineManager();
        var scriptEngine = scriptEngineManager.getEngineByName("Java");
        var evalString = "k1 = \"test\"; k2 = \"tset\";";
        scriptEngine.eval()
        var evalClass = (Class<?>) scriptEngine.eval("" +
                "class Example {" +
                "    String k1, k2;" +
                "    Example() {" +
                "    }" +
                "    void run() {" +
                "        " + evalString + "" +
                "    }" +
                "}");
        var evalCtor = evalClass.getDeclaredConstructor();
        evalCtor.setAccessible(true);
        var evalObj = evalCtor.newInstance();
        Method evalRunMethod = evalClass.getDeclaredMethod("run");
        evalRunMethod.setAccessible(true);
        evalRunMethod.invoke(evalObj);
        Field evalK1Field = evalClass.getDeclaredField("k1");
        evalK1Field.setAccessible(true);
        var k1 = evalK1Field.get(evalObj);
        System.out.println(k1);


Вариант 3 (то, что ты описал, но без работы с диском, требует com.google.jimfs:jimfs:1.1):


        var javaCompiler = ToolProvider.getSystemJavaCompiler();
        var fileManager = javaCompiler.getStandardFileManager(null, ENGLISH, UTF_8);
        var fileSystem = Jimfs.newFileSystem(Configuration.unix());
        var evalString = "k1 = \"test\"; k2 = \"tset\";";
        Files.writeString(fileSystem.getPath("/Example.java"), "" +
                "public class Example implements Runnable {" +
                "    public String k1, k2;" +
                "    public void run() {" +
                "        " + evalString + "" +
                "    }" +
                "}");
        var sources = fileManager.getJavaFileObjects(fileSystem.getPath("/Example.java"));
        javaCompiler.getTask(null, fileManager, null, null, null, sources).call();
        var bytecode = Files.readAllBytes(fileSystem.getPath("/Example.class"));
        var classLoader = new ClassLoader() {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                if (name.equals("Example")) {
                    return defineClass(name, bytecode, 0, bytecode.length);
                }
                return super.findClass(name);
            }
        };
        var exampleClass = classLoader.findClass("Example");
        var exampleObj = (Runnable) exampleClass.getConstructor().newInstance();
        exampleObj.run();
        System.out.println(exampleClass.getField("k1").get(exampleObj));


Эти примеры из этой темы.