标签: bytecode

字节码注入在哪里发生?

动机

我有一个SomeObject.java文件:

class SomeObject {
   String name;
}
Run Code Online (Sandbox Code Playgroud)

编译它会创建一个包含字节码的SomeObject.class文件.

0xCAFEBABE...
Run Code Online (Sandbox Code Playgroud)

如果我们在JVM上使用SomeObject,它将由当前的类加载器加载,并且一切正常.

现在让我们假设我想要一些动态代码生成.我可以写我的自定义注释

@Target(ElementType.TYPE)
public @interface Data {
   ...
}
Run Code Online (Sandbox Code Playgroud)

并将其作为修饰符添加到类声明中:

@Data
class SomeObject {
   String name;
}
Run Code Online (Sandbox Code Playgroud)

我也可以在运行时保留它@Retention(RetentionPolicy.RUNTIME):

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Data {
   ...
}
Run Code Online (Sandbox Code Playgroud)

用于字节码注入的注释在哪里?在使用适当的运行时保留注释加载类时,类加载器是否会注入字节码,如下图所示:

source -(compile)-> bytecode -(classloader bytecode injection)-> injected bytecode -(classloading)-> JVM loaded bytecode   
Run Code Online (Sandbox Code Playgroud)

annotations bytecode classloader bytecode-manipulation

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

javac也是内联的吗?

我正在玩javap和一些非常简单的代码,这引发了一个 - 希望很简单 - 的问题.

这是代码优先:

public class Main {


  public static void main(String[] args) throws Exception {
    System.out.println(m1());
    System.out.println(m2());
  }

    private static String  m1() {
        return new String("foobar");
    }

    private static String m2() {
        String str = "foobar";
        return new String(str);
    }

}
Run Code Online (Sandbox Code Playgroud)

现在我编译了代码并查看了输出(现在省略-verbose).

$ javap -c Main.class 
Compiled from "Main.java"
public class Main {
  public Main();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: getstatic     #2                  // …
Run Code Online (Sandbox Code Playgroud)

jvm bytecode javap

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

是否可以使用 if 和 while 将所有控制流图转换回?

我想知道从单个方法(不允许递归)的典型JVM 字节码(参见如何)获得的所有控制流图是否都可以转换回等效的s 和s 代码。ifwhile

如果不是,则无法转换回ifs 和whiles的最小 JVM 字节码序列是多少?

jvm if-statement bytecode while-loop control-flow-graph

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

函数代码中的R字节码引用

在检查函数的R代码时,它列出了一个字节码(例如,对于glm):. 我到处寻找一个简单的解释,实际上是"0x7f8f3c954540".我知道字节码是什么,但我假设"0x7f8f3c954540"实际上并不是glm函数整个代码的高度压缩机器可处理版本.它是CRC,它在内存中的位置的链接,还是前几位?

bytecode r function

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

LLVM IR打印一个数字

我正在尝试打印一个数字,但我收到错误,说我的打印功能错误:

define i32 @main() {
entry:
  %d = shl i32 2, 3
  %call = call i32 (i8*, ...)* @printf(i8* %d)
  ret i32 1
}

declare i32 @printf(i8*, ...)
Run Code Online (Sandbox Code Playgroud)

这是错误:

Error in compilation: /bin/this.program: llvm.ll:4:44: error: '%d' defined with type 'i8'
  %call = call i32 (i8*, ...)* @printf(i8* %d)
                                       ^
Run Code Online (Sandbox Code Playgroud)

还有其他一些打印功能可以解决这个问题吗?

assembly bytecode llvm

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

在运行时修改函数(拉出局部变量)

想象一下这个简单的函数创建一个变量的修改值default,modified:

default = 0
def modify():
    modified = default + 1
    print(modified)  # replace with OS call, I can't see the output

modify()  # 1
default  # 0
Run Code Online (Sandbox Code Playgroud)

拆解:

import dis
dis.dis(modify)
2           0 LOAD_GLOBAL              0 (default)
            3 LOAD_CONST               1 (1)
            6 BINARY_ADD
            7 STORE_FAST               0 (modified)
3          10 LOAD_GLOBAL              1 (print)
           13 LOAD_FAST                0 (modified)
           16 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
           19 POP_TOP
           20 LOAD_CONST               0 (None)
           23 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

我不能改变这个功能modify(),但我知道它的内容是直接(我可以看到代码)还是间接(反汇编).我需要它是获取modified …

python bytecode function disassembly

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

此代码如何使用保留的关键字作为字段名称?

尝试对服务器应用程序启动进行故障排除时,我在旧版Java字节码中发现以下构造。我的IDE反编译了一些第三方库,我很好奇它的有效性-从来没有见过关键字 可以用作字节码中的字段名称

字节码版本为48.0(Java 1.4)。

public final class f implements UserContext{

private final String try;
private final UserInfo do;

// a lot of code here 

public UserInfo getUserInfo(){
    return this.do;
}

public String getViewName(){
    return this.try;
}

}
Run Code Online (Sandbox Code Playgroud)

好像该库是使用一些混淆功能进行编译的,但是如何在JVM级别上呢?是否允许在JVM启动时没有特殊标志?

更新:该UserInfo字段的正确getter名称是getUserInfo-很抱歉使每个人都对具有不同返回值的方法的模棱两可的命名感到困惑,这是一个复制粘贴问题,因为代码位于没有直接访问该站点的远程计算机上。

java bytecode jvm-bytecode

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

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

我有一个类似的界面:

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
查看次数

垃圾收集器如何更新推送到操作数堆栈的引用?

在堆中移动对象时,JVM 可以轻松更新局部变量、静态引用、类实例或对象数组实例的引用。但是它如何更新推送到操作数堆栈的引用呢?

java garbage-collection jvm bytecode

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

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
查看次数