我正在使用 ASM 生成一些字节码并动态执行它。但在某些情况下,我需要调用私有构造函数,但我不知道如何调用。我知道可以通过反射(setAccessible)调用私有构造函数,但是我如何直接在字节码/jvm中执行此操作?
mv.visitMethodInsn(
INVOKESPECIAL, target.byteCodeName(), "<init>", "()V", false
)
Run Code Online (Sandbox Code Playgroud)
当 JVM 执行此代码时,它会抛出 java.lang.IllegalAccessError。
我很难理解字节码操作/增强和 Java Instrumentation API 之间的依赖关系。
根据我的理解,要进行任何字节码操作/增强,我们有两种选择
*.class然后应该执行一些其他库/应用程序来进行操作。我不确定的事情:
是否有诸如构建时字节码操作之类的东西以及支持该操作的框架/库是什么(例如 Javassist、ASM)它们是否使用某种通用方法或只是读取和解析字节码,然后为您提供修改它的方法?
加载时操作是否仅依赖于 Java Instrumentation API?意味着所有可用的框架/库(例如 Javassist、ASM)都使用 javaagent 来进行操作?
请注意,我对这个主题的经验非常少,因此我有可能误解或错过了一些概念。我试图将这个复杂的主题归结为一些简单的解释,即使它非常笼统或使用类比来演示。
我试图使用Java字节码工程库ASM来执行静态分析.我有这种情况,我想检查分配给字段的变量.
我有MethodVisitor实现该visitFieldInsn()方法.我特意找这个putfield命令.那没问题.问题是,当我遇到时putfield,我希望能够访问将分配给该字段的变量.具体来说,我想访问有关变量类型的信息.
目前我真的只需要查看堆栈顶部的内容,但如果有更通用的方法来检查它,那就更好了.
有没有办法使用ASM来检查堆栈上的变量?
我使用Java ASM编写一个简单的程序来生成通过编译以下类生成的字节代码.
public class Main {
public static void main(String[] args) {
System.out.println("Test");
}
}
Run Code Online (Sandbox Code Playgroud)
我编写的用于生成此类的字节码的代码如下所示.
public class CodeGenerator {
public void generateClass()
{
ClassWriter cw=new ClassWriter(Opcodes.NULL);
FieldVisitor fv;
MethodVisitor mv;
cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Main", null, "java/lang/Object", null);
mv=cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(Opcodes.AALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv=cw.visitMethod(Opcodes.ACC_PUBLIC+ Opcodes.ACC_STATIC, "Main", "([Ljava/lang/String;)V", null, null);
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream");
mv.visitLdcInsn("Test");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
cw.visitEnd();
this.WriteClass(cw);
}
public void WriteClass(ClassWriter cw){
FileOutputStream fos; …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个带有.class文件的程序,并收集.class文件的所有方法以及每个方法的内容.这是我的代码
public class ClassReaderTest1 {
public static void main(String[] args) throws Exception{
InputStream in = new FileInputStream("*.class");
ClassReader reader = new ClassReader(in);
ClassNode classNode = new ClassNode();
reader.accept(classNode,0);
@SuppressWarnings("unchecked")
final List<MethodNode> methods = classNode.methods;
for(MethodNode m: methods){
InsnList inList = m.instructions;
System.out.println(m.name);
for(int i = 0; i< inList.size(); i++){
System.out.println(" " + Integer.toHexString(inList.get(i).getOpcode()));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的输出
init>
ffffffff
ffffffff
19
b7
b1
ffffffff
main
ffffffff
ffffffff
b2
12
b6
ffffffff
ffffffff
3
36
ffffffff
ffffffff
b1
ffffffff
Run Code Online (Sandbox Code Playgroud)
最终我不想打印这些值,我只是希望能够在我的程序中引用它们(我正在尝试检查我是否得到了正确的值).我按预期得到方法,但方法的内容对我没有意义.我认为这些不是操作码; …
我使用ASM基于类生成超类ToOverride.我想覆盖它的ToOverride::getValue方法.上面提到的类看起来像:
public abstract class ToOverride {
Object getValue(String str, Object arg) throws Exception {
throw new IllegalStateException("PARENT!");
}
Object justMethod() {
return "test";
}
}
Run Code Online (Sandbox Code Playgroud)
在普通的java中,期望的类看起来像这样:
public class GeneratedInheritor extends ToOverride {
@Override
Object getValue(String str, Object arg) throws Exception {
return str + arg;
}
}
Run Code Online (Sandbox Code Playgroud)
我生成了后一个类,导致后面的字节码.
// class version 49.0 (49)
// access flags 0x21
public class com/example/GeneratedInheritor extends com/example/ToOverride {
// access flags 0x1
public <init>()V
ALOAD 0
INVOKESPECIAL com/example/ToOverride.<init> ()V
RETURN
MAXSTACK …Run Code Online (Sandbox Code Playgroud) 假设某人给了我以下源代码的Java字节码:
class MyClass {
public static void foo() {
final String bar = "Hello";
}
}
Run Code Online (Sandbox Code Playgroud)
我想扫描这个类中的所有方法MyClass.如果任何方法包含一个final String被调用的变量bar,我需要输出变量的文字值.在这种情况下,Hello.
我设法得到bar方法中调用的变量如下:
// Scala code
import scala.collection.JavaConversions._
import org.objectweb.asm._
import org.objectweb.asm.tree._
def processClass(is:java.io.InputStream) = {
val cn = new ClassNode
val cr = new ClassReader(is)
cr.accept(cn, 0)
is.close
val methods = cn.methods.asInstanceOf[java.util.List[MethodNode]]
val m = methods(0) // get first method as an example
val vars = m.localVariables.asInstanceOf[java.util.List[LocalVariableNode]];
val bar = vars.find(_.name == "bar").find(v …Run Code Online (Sandbox Code Playgroud) 据我了解,这两个框架都是静态的,可将监视代码注入类代码。那么区别是什么呢?
我正在尝试删除test()以下程序中的方法主体,以便不向控制台打印任何内容.我正在使用ASM 5.2,但我尝试的一切似乎都没有任何影响.
有人可以解释我做错了什么,并指出了一些关于ASM的最新教程或文档吗?我在Stackoverflow和ASM网站上发现的几乎所有内容都显得过时和/或无用.
public class BytecodeMods {
public static void main(String[] args) throws Exception {
disableMethod(BytecodeMods.class.getMethod("test"));
test();
}
public static void test() {
System.out.println("This is a test");
}
private static void disableMethod(Method method) {
new MethodReplacer()
.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, method.getName(), Type.getMethodDescriptor(method), null, null);
}
public static class MethodReplacer extends ClassVisitor {
public MethodReplacer() {
super(Opcodes.ASM5);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud) 我有一些方法,其中包含像ILOAD这样的内容,我希望以某种方式在此指令之后获取堆栈的值.不只是打字,而是确切的价值.我知道我需要模拟方法执行才能做到这一点,但我不知道如何正确地做到这一点.
我有这样的测试方法叫main:
sipush 15649
istore_0 /* c */
getstatic java/lang/System.out:Ljava/io/PrintStream;
bipush 45
bipush 11
iload_0 /* c */
...
Run Code Online (Sandbox Code Playgroud)
我希望得到价值,加载iload_0.我试图制作分析器,然后看到帧值,但它们只包含值的类型,而不是我想要的.
ClassReader cr = new ClassReader(new FileInputStream(new File("input.class")));
ClassNode cn = new ClassNode(Opcodes.ASM5);
cr.accept(cn, 0);
Iterator<MethodNode> methods = cn.methods.iterator();
while (methods.hasNext()) {
MethodNode mn = methods.next();
if (!mn.name.equals("main")) continue;
AbstractInsnNode[] nodes = mn.instructions.toArray();
Analyzer analyzer = new Analyzer(new BasicInterpreter());
analyzer.analyze(cn.name, mn);
int i = -1;
for (Frame frame : analyzer.getFrames()) {
i++;
if (frame == null) continue; …Run Code Online (Sandbox Code Playgroud) java ×9
bytecode ×4
aspectj ×1
assembly ×1
classloader ×1
hook ×1
inject ×1
jvm ×1
jvm-bytecode ×1
opcode ×1
overriding ×1
scala ×1