标签: java-bytecode-asm

如何使用ASM为方法和类更改最终修饰符

实际我在类中有一个方法如下.

public static final void print(String str){
       System.out.println(str);
}
Run Code Online (Sandbox Code Playgroud)

我想final从met hod中删除修饰符.所以在这之后,我的方法将如下所示:

public static void print(String str){   
       System.out.println(str);
}
Run Code Online (Sandbox Code Playgroud)

使用ASM,我们将获得此信息

public MethodVisitor visitMethod(int access, String name, 
                                 String desc, String signature, 
                                 String[] exceptions) { }
Run Code Online (Sandbox Code Playgroud)

在上面,我认为要实现上述情况,我们需要使用access参数.但访问是公共+静态+最终的总和.如何删除最终是我的问题?

类级最终修饰符也一样吗?

java java-bytecode-asm

2
推荐指数
1
解决办法
1221
查看次数

如何使用ASM进行字节码转换后定义类(类文件版本0.0)

我无法在使用 ASM 库修改字节码后加载类。

这里是恒等变换器,我希望得到与字节一大小相同的修改后的数组,但它短两倍!(439 比 278)

    String path = SimpleClass.class.getName().replace(".", "/") + ".class";
    ClassLoader classLoader = SimpleClass.class.getClassLoader();
    InputStream is = classLoader.getResourceAsStream(path);

    byte[] bytes = IOUtils.toByteArray(is);

    ClassReader reader = new ClassReader(bytes);
    ClassWriter writer = new ClassWriter(reader, 0);
    byte[] modified = writer.toByteArray();
Run Code Online (Sandbox Code Playgroud)

无法加载并没有什么了不起的。我怀疑标头被截断,但两个数组中的第一个字节是相同的。

-54, -2, -70

static class ByteClassLoader extends ClassLoader {
    public Class define(String name, byte[] body) {
        return defineClass(name, body, 0, body.length);
    }
}

ByteClassLoader myLoader = new ByteClassLoader();
Class myClass = myLoader.define("Ooo", modified);
Run Code Online (Sandbox Code Playgroud)

失败并出现错误:

java.lang.UnsupportedClassVersionError: Ooo has been compiled …
Run Code Online (Sandbox Code Playgroud)

java jvm java-bytecode-asm

2
推荐指数
1
解决办法
1405
查看次数

使用asm java时出现验证错误

所以基本上我试图System.out.println("hey"); 在方法的最后添加一个简单的.我使用了树API.但是我一直收到这个错误:

java.lang.VerifyError:期望分支目标38处的stackmap帧

这是我的代码:

public class MethodNodeCustom extends MethodNode {

    public MethodNodeCustom(int paramInt, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString) {
        this(327680, paramInt, paramString1, paramString2, paramString3, paramArrayOfString);
        return;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public MethodNodeCustom(int paramInt1, int paramInt2, String paramString1, String paramString2, String paramString3,
        String[] paramArrayOfString) {
        super(paramInt1);
        this.access = paramInt2;
        this.name = paramString1;
        this.desc = paramString2;
        this.signature = paramString3;
        this.exceptions = new ArrayList((paramArrayOfString == null) ? 0 : paramArrayOfString.length);
        int i = ((paramInt2 & 0x400) != 0) …
Run Code Online (Sandbox Code Playgroud)

java bytecode bytecode-manipulation java-bytecode-asm jvm-bytecode

2
推荐指数
1
解决办法
481
查看次数

获取方法中局部变量的数量

所以我有一些类已插入“虚拟方法调用”;即具有空主体的专用类中的静态方法。

这个想法是获取在方法调用之前推送到堆栈的参数,将它们存储在局部变量中,然后用实际实现替换方法调用。

为了看看当地人是如何处理的,我运行

A.java

package asmvisit;

public class A {
    long y;

    public long doSomething(int x, A a){
        if(a == null){
            this.y = (long)x;
            return -1L;
        }
        else{
            long old = y;
            this.y += (long)x;
            return old;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

通过文本编辑器(代码在帖子底部)。

正如您在输出中看到的(也在帖子的底部),局部变量

    LOCALVARIABLE old J L4 L6 3
    LOCALVARIABLE this Lasmvisit/A; L0 L6 0
    LOCALVARIABLE x I L0 L6 1
    LOCALVARIABLE a Lasmvisit/A; L0 L6 2
Run Code Online (Sandbox Code Playgroud)

在方法的最后被访问。

从技术上讲,我们将被允许更早地访问它们,但我明白为什么在任意位置插入局部变量可能会搞乱编号 - 以及程序。

因此,在我看来,添加更多局部变量的唯一安全方法是对每个方法运行两次:

  • 除了计算局部变量访问次数之外,什么都不做
  • 一旦实际修改代码,跟踪“生成”的局部变量,但将实际生成(即访问局部变量)延迟到 之前visitMaxs,使用计数器来跟踪新局部变量最终将拥有的索引。

有没有更简单的替代方案,不需要两次通过?

文本化器

package asmvisit; …
Run Code Online (Sandbox Code Playgroud)

java instrumentation bytecode java-bytecode-asm

2
推荐指数
1
解决办法
1502
查看次数

使用JDB(或类似程序)调试ASM生成的字节码

因此,我有一些功能不良的代码可以调试在某些地方抛出NPE的地方,我想逐步介绍一些生成的方法,以尝试找出原因。

除了盲目踏步不是真正有用的。

Thread-4[1] list
Source file not found: Foo.java
Thread-4[1] locals
Local variable information not available.  Compile with -g to generate variable information
Run Code Online (Sandbox Code Playgroud)

代码已生成,因此当然没有.java可用于JDB的文件。

而且由于我不使用javac进行编译,因此也没有指定任何-g标志。

我可以告诉JDB给我看一下字节码吗(他显然有字节码,因为否则Java将没有任何执行力)?

我可以告诉ASM生成本地信息,就像使用它进行编译一样javac -g吗?

还是那里有一个有用的调试器可以满足我的需求?

java debugging bytecode jdb java-bytecode-asm

2
推荐指数
1
解决办法
544
查看次数

构造函数字节码

ASM引导谈到构造函数:

package pkg;
public class Bean {
  private int f;
  public int getF() {
      return this.f;
  }
  public void setF(int f) {
      this.f = f;
  }
}
Run Code Online (Sandbox Code Playgroud)

Bean类还具有由编译器生成的默认公共构造函数,因为程序员没有定义任何显式构造函数。此默认的公共构造函数生成为 Bean() { super(); }。该构造函数的字节码如下:

ALOAD 0
INVOKESPECIAL java/lang/Object <init> ()V
RETURN
Run Code Online (Sandbox Code Playgroud)

第一条指令压this入操作数堆栈。第二条指令从堆栈中弹出该值,并调用类中<init> 定义的方法Object。这对应于super() 调用,即对超类的构造函数的调用Object。您可以在此处看到,在编译类和源类中,构造函数的名称不同:在编译类中,它们总是命名为<init>,而在源类中,它们具有定义它们的类的名称。最后,最后一条指令返回给调用者。

this在构造函数的第一条指令之前,JVM已知的值如何?

java bytecode-manipulation java-bytecode-asm jvm-bytecode

2
推荐指数
1
解决办法
580
查看次数

用动态生成的类替换反射调用

我有一个类似的界面:

public interface Getter {
    Object get(Params params);
}
Run Code Online (Sandbox Code Playgroud)

我使用对不同方法的反射调用来实现:

public class GetterImpl implements Getter {

    private final Object target;
    private final Method method; //doStuff method

    public GetterImpl(Object target, Method method) {
        this.target = target;
        this.method = method;
    }

    @Override
    public Object get(Params params) {
        //both the target and arguments depend on Params
        return method.invoke(chooseTarget(params), prepareArgs(params));
    }

    private Object chooseTarget(Params params) {
        if (params.getTargetOverride() != null) {
            return params.getTargetOverride();
        }
        return target;
    }

    private Object[] prepareArgs(Params params) {
        ...
    } …
Run Code Online (Sandbox Code Playgroud)

java code-generation bytecode java-bytecode-asm byte-buddy

2
推荐指数
1
解决办法
275
查看次数

Java ASM 字节码 - 查找属于特定方法调用的所有指令

你好。

我想找到方法调用开始结束之间的指令范围。
我不想简单地更改方法调用所有者/名称/描述。

有了预期的结果,我希望能够做到:

  1. 完全删除一个方法调用
  2. 通过在前面或后面添加新参数来修改方法调用


我一直在尝试不同的技术来实现这一目标:

  1. ASM 分析器(使用 SourceInterpreter)
  2. 循环指令集,向前和向后,通过计算指令计数或计算堆栈高度来尝试定位startend
  3. 通过 StackOverflow 搜索(没有发现导致预期行为的任何内容)


我会给你一些我想要什么的例子,以防这里有任何混淆。
首先,看看我下面的测试代码,然后回到这里。

我希望找到/删除整个方法调用anotherMethod4并将其替换为一个简单的true,从而生成以下代码:

    System.out.println(
        anotherMethod1(
            anotherMethod2("a", "b") ?
                "c" : anotherMethod3("d", "e") ? "f" : "g",
                true ? "j" : "k"
        ) ? "l" : "m"
    );
Run Code Online (Sandbox Code Playgroud)

我希望找到/删除整个方法调用anotherMethod1并将其替换为一个简单的false,从而生成以下代码:

    System.out.println(
        false ? "l" : "m"
    );
Run Code Online (Sandbox Code Playgroud)


我希望删除对 的整个方法调用System.out.println,从而生成以下代码:

    private Main()
    {

    }
Run Code Online (Sandbox Code Playgroud)


这一定是可能的吗?

这是我当前的测试代码:

private Main()
{
    System.out.println(
        anotherMethod1(
            anotherMethod2("a", …
Run Code Online (Sandbox Code Playgroud)

java bytecode java-bytecode-asm

2
推荐指数
1
解决办法
578
查看次数

为什么在 Java 字节码中跳转而不是返回?

背景

我编译了以下方法:

public static final boolean equalTo(final int x, final int y) {
    return x == y;
}
Run Code Online (Sandbox Code Playgroud)

可以javap看到为其生成了以下字节码:

  public static final boolean equalTo(int, int);                                                                                                                                                                 
    descriptor: (II)Z                                                                                                                                                                                            
    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL                                                                                                                                                            
    Code:                                                                                                                                                                                                        
      stack=2, locals=2, args_size=2                                                                                                                                                                             
         0: iload_0                                                                                                                                                                                              
         1: iload_1                                                                                                                                                                                              
         2: if_icmpne     9                                                                                                                                                                                      
         5: iconst_1                                                                                                                                                                                             
         6: goto          10                                                                                                                                                                                     
         9: iconst_0                                                                                                                                                                                             
        10: ireturn                                                                                                                                                                                              
      LineNumberTable:                                                                                                                                                                                           
        line 72: 0                                                                                                                                                                                               
      StackMapTable: number_of_entries = 2                                                                                                                                                                       
        frame_type = 9 /* same */                                                                                                                                                                                
        frame_type = 64 /* same_locals_1_stack_item */                                                                                                                                                           
          stack = [ int ]                                                    
Run Code Online (Sandbox Code Playgroud)

我编写了 …

java jvm bytecode java-bytecode-asm jvm-bytecode

2
推荐指数
1
解决办法
245
查看次数

即使设置了ClassWriter(COMPUTE_MAX + COMPUTE_STACK),ASM(来自ObjectWeb)也无法正确计算MaxStack

尝试加载使用ASM生成的类时,我得到了预期的ClassVerifyErrors.在进一步检查时,我可以看到jvm是正确的,并且该方法所讨论的具有无效的MAX_STACK值.奇怪的是我正在使用自动计算堆栈和最大本地选项,所以这不应该是一个问题...使用无效选项的方法非常简单,但结果是错误的字节码.

我编写了一个带有预期方法的类,并将我的asm生成的类与javac生成的类比较,字节代码匹配,唯一的错误是max stack为0,这是错误的,而javac设置的值为2.

我想避免自己计算最大堆栈/本地人.

java assembly java-bytecode-asm

1
推荐指数
1
解决办法
1358
查看次数