[英]“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()”中。
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);");
}
}
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.