简体   繁体   English

“使用Groovy时没有这样的属性:for class:Script1”(字符串到反射代码)

[英]“No such property: for class: Script1” during using Groovy(String to reflection code)

I am trying to use Groovy in order to convert string to the reflection code but I have "No such property" exception. 我试图使用Groovy将字符串转换为反射代码,但我有“没有这样的属性”异常。

I have tried to make global all variables, change the reflection code and put @Field notation but problem still remaining. 我试图制作全局所有变量,更改反射代码并放置@Field表示法,但问题仍然存在。 I put Groovy code inside "runTestSamples()". 我将Groovy代码放在“runTestSamples()”中。

MainClass - Test2 MainClass - Test2

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.jacoco.agent.AgentJar;
import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.data.SessionInfoStore;
import org.jacoco.core.instr.Instrumenter;
import org.jacoco.core.runtime.IRuntime;
import org.jacoco.core.runtime.LoggerRuntime;
import org.jacoco.core.runtime.RuntimeData;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class Test2 {

    private Runnable targetInstance;
    public Class<?> targetClass;
    private static HashMap<Integer, String> testSamples;
    private static HashMap<String, Integer> coverageData;
    public String targetName;
    public IRuntime runtime;
    public Instrumenter instr;
    public InputStream original;
    public byte[] instrumented;
    public RuntimeData data;
    public MemoryClassLoader memoryClassLoader;

    static Test2 t2 = new Test2();
    int a;

    public static void main(String[] args) throws Exception {
        testSamples = new HashMap<Integer, String>();

        coverageData = new HashMap<String, Integer>();

        try {
            t2.execute();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void execute() throws Exception {
        testSamples = new HashMap<Integer, String>();
        coverageData = new HashMap<String, Integer>();
        targetName = SUTClass.class.getName();
        runtime = new LoggerRuntime();
        instr = new Instrumenter(runtime);
        original = getTargetClass(targetName);
        instrumented = instr.instrument(original, targetName);
        original.close();
        data = new RuntimeData();
        runtime.startup(data);
        memoryClassLoader = new MemoryClassLoader();
        memoryClassLoader.addDefinition(targetName, instrumented);
        targetClass = (Class<? extends Runnable>) memoryClassLoader.loadClass(targetName);
        targetInstance = (Runnable) targetClass.newInstance();
        // Test samples
        runTestSamples();
        targetInstance.run();
        final ExecutionDataStore executionData = new ExecutionDataStore();
        final SessionInfoStore sessionInfos = new SessionInfoStore();
        data.collect(executionData, sessionInfos, false);
        runtime.shutdown();
        final CoverageBuilder coverageBuilder = new CoverageBuilder();
        final Analyzer analyzer = new Analyzer(executionData, coverageBuilder);
        original = getTargetClass(targetName);
        analyzer.analyzeClass(original, targetName);
        original.close();

        for (final IClassCoverage cc : coverageBuilder.getClasses()) {
            coverageData.put("coveredInstructions", cc.getInstructionCounter().getCoveredCount());
        }

        System.out.println(coverageData.get("coveredInstructions"));
        System.out.println(a);

    }

    public static class MemoryClassLoader extends ClassLoader {
        private final Map<String, byte[]> definitions = new HashMap<String, byte[]>();

        public void addDefinition(final String name, final byte[] bytes) {
            definitions.put(name, bytes);
        }

        @Override
        protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
            final byte[] bytes = definitions.get(name);
            if (bytes != null) {
                return defineClass(name, bytes, 0, bytes.length);
            }
            return super.loadClass(name, resolve);
        }

    }

    private InputStream getTargetClass(final String name) {
        final String resource = '/' + name.replace('.', '/') + ".class";
        return getClass().getResourceAsStream(resource);
    }

    public void runTestSamples() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
            NoSuchMethodException, SecurityException, ClassNotFoundException {

        // Test case
        targetClass.getMethod("f", int.class, int.class).invoke(targetInstance, 2, 9);

        // Groovy String to code
        Binding binding = new Binding();
        GroovyShell shell = new GroovyShell(binding);
        Object value = shell.evaluate("targetClass.getMethod(\"f\", int.class, int.class).invoke(targetInstance, 2, 9);");

    }

}

Exception 例外

groovy.lang.MissingPropertyException: No such property: targetClass for class: Script1
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:65)
    at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:51)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:309)
    at Script1.run(Script1.groovy:1)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:437)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:475)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:446)
    at Test2.runTestSamples(Test2.java:119)
    at Test2.execute(Test2.java:66)
    at Test2.main(Test2.java:43)

the problem in this code: 这段代码中的问题:

Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate("targetClass.getMethod(\"f\", int.class, int.class).invoke(targetInstance, 2, 9);");

when you call shell.evaluate imagine that you call absolutely new class that doesnot know anything about your current variables like targetClass 当你调用shell.evaluate想象你调用绝对新的类,它不知道你当前的变量,比如targetClass

so, GroovyShell telling that there is no such property: targetClass 所以, GroovyShell告诉我们没有这样的属性: targetClass

to fix it - you have just to populate binding - pass the variables values and names that should be visible inside the shell.evaluate(...) . 修复它 - 你只需要填充绑定 - 传递应该在shell.evaluate(...)可见的变量值和名称。

Binding binding = new Binding();
binding.setVariable("target", targetClass) //pass targetClass as target variable name
binding.setVariable("instance", targetInstance)
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate("target.getMethod(\"f\", int.class, int.class).invoke(instance, 2, 9)");

another point - groovy is already dynamic language and you could simplify your nested script from this: 另一点 - groovy已经是动态语言,你可以从这简化你的嵌套脚本:

target.getMethod("f", int.class, int.class).invoke(instance, 2, 9)

to this: 对此:

instance."f"(2, 9)

and finally maybe you don't need to use the groovyshell because the following code dynamycally calls the method: 最后也许您不需要使用groovyshell,因为以下代码动态调用该方法:

class A{
    def f(int a, int b){ a+b }
}

def instance = new A()
def method = "f"
def params = [2,9]

println instance."${method}"(params)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM