MethodNode を直接作成して分析できるかどうか疑問に思っています。したがって、テストするコードを以下に記述します。
ClassNode classNode = new ClassNode(Opcodes.ASM5);
classNode.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(BaseTemplate.class), null);
constructClass(classNode, className);
//THREAD SAFE but looks badly.
if(_node == null){
synchronized(this){
if(_node==null){
MethodType tmpType = MethodType.methodType(int.class);
_node = (MethodNode) classNode.visitMethod(ACC_PUBLIC, Constants.INVOKE_EXACT, tmpType.toMethodDescriptorString(),
null, new String[] { "java/lang/Throwable" });
_node.visitCode();
_node.visitInsn(ICONST_0);
_node.visitInsn(IRETURN);
//_node.visitMaxs(-1, -1);
_node.visitEnd();
Analyzer _analyzer = new Analyzer(new SourceInterpreter());
try {
_analyzer.analyze(className, _node);
} catch (AnalyzerException e) {
e.printStackTrace();
}
}
}
}
残念ながら、次の呼び出し時に例外がスローされ_analyzer.analyze()
ます。
java.lang.IndexOutOfBoundsException: Trying to access an inexistant local variable 0
at org.objectweb.asm.tree.analysis.Frame.setLocal(Frame.java:175) ~[na:5.0.3]
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:165) ~[na:5.0.3]
at java.lang.invoke.MethodHandle.compile(MethodHandle.java:1222) ~[na:na]
と の未設定が原因だと思いmaxStack
ますmaxLocals
。maxStack
とを正しく計算してmaxLocals
、ここで呼び出す必要があるようvisitMax()
です。両方の値を計算せずに他の方法はありますか?
以前に使用した別の方法は、次のようなコードです。
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(BaseTemplate.class), null);
constructClass(cw, className);
//THREAD SAFE but looks badly.
if(_node == null){
synchronized(this){
if(_node==null){
_node = new MethodNode(ACC_PUBLIC, Constants.INVOKE_EXACT, type.toMethodDescriptorString(),
null, new String[] { "java/lang/Throwable" });
generateMethod(_node, className);
}
}
}
_node.accept(cw);
cw.visitEnd();
ClassNode classNode = new ClassNode(ASM5);
ClassReader reader = new ClassReader(new ByteArrayInputStream(cw.toByteArray()));
reader.accept(classNode, 0);
//Then extract MethodNode from ClassNode and make analyzation.
これは機能しますが、MethodNode の複数回の訪問が含まれているため、私は好きではありません。
目的:
クラスインスタンスごとに MethodNode を生成したいのですが、各インスタンスは生成されたインスタンスへの参照を保持します。最初のコードでは、ClassNode とターゲット MethodNode を直接作成し、その間に let が_node
ターゲット MethodNode を直接指すようにするというのが私の考えです。このようにすると、ClassNode 全体へのアクセスは 1 回だけです。つまり、ClassNode の作成中に MethodNode を取得します。
2 番目の部分のコードについては、ClassWriter を使用してアクセスします。の後cw.visitEnd()
、ClassNode、つまり を取得するために、再度アクセスする必要がありreader.accept(classNode, 0);
ます。授業参観は2回あります。