问题标签 [jvm-bytecode]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 如何使用 asm 将简单的调用语句添加到类文件
考虑我有这个java程序。
现在我有一个 ASM 代码可以遍历方法节点,并且可以访问方法中的指令。假设我添加了调用方法和用于添加简单打印语句的 ldc。[![在此处输入图片描述][1]][1]
这有助于打印语句...假设如果我有一个 ALOAD 语句,即有一个变量用法,我想调用编码函数调用,以便在使用过程中对变量进行编码。所以我的计划是添加编码在 ALOAD 语句之后调用 stmt。如何做到这一点?
java - 什么是引导方法参数 - Java 字节码
具有 3 个方法参数的引导方法:
具有单个参数的引导方法:
我已经开始研究 Java 字节码并想知道:
- 什么是引导方法参数?
- 第一个实例的第二个参数似乎引用了 lamda 表达式。那是什么?
注意: 这不是关于如何确定对象是 lambda。我只想通过检查字节码来了解什么是引导方法参数,以及它与 lambda 表达式的相关性。
java - 在 java 字节码中创建一个 char 数组会产生一个 Object
我碰壁了,试图用 Java 编写一个简单的编译器,使用 ASM。基本上,我正在尝试将字符串添加在一起,但无法弄清楚为什么我的代码无法这样做。问题在于以下代码行的编译方式:
其中 i 是一个已初始化的数组。行p = "Hi"; 编译为:
请注意,我故意将字符串“Hi”视为 char 数组,而不是直接视为 String 对象。反编译的时候是这样的:
因此,由于 {'H', 'i'} 不是 Object 的正确构造函数,因此程序不会执行。现在,我的困惑,以及我来到stackoverflow的原因是当行p = p + i[0]; 从程序中删除,或替换为不使用数组的,例如p = p + 5;, 行p = "Hi"; 再次以完全相同的方式编译:
反编译时,同一行内容如下:
程序运行得很好。我完全不知道这里发生了什么,也不知道如何解决它。为了反编译 .class 文件,我使用了这个反编译器。我想知道为什么在这两种情况下完全相同的字节码反编译不同。
java - 如何在编译时未知的索引处从局部变量加载引用?
据我了解 JVM 字节码规范,
aload index
将找到的引用推index
送到当前堆栈帧上。就我而言,我需要aload
在存储在局部变量中的索引处找到一个引用 - 像这样:aload (iload 2)
.
(这怎么可能?
java - 如果在 ClassWriter 中设置了 COMPUTE_FRAMES,ASM 会跳过类
我一直在研究与 maven-surfire-plugin 一起运行的 Java 代理。代理应该能够在三个不同的点将使用 ASM 库的方法调用注入到加载的方法中: 1) 在每个方法的开头;2) 在每个方法结束时;3) 在某些行(见下文)。为此,我实现了一个 premain 方法,它为 Java 工具添加了一个新的转换器。然后,transform 方法为它应该转换的每个类创建一个新的 ClassWriter 和 ClassVisitor(属于 ASM 库)。
不幸的是,我遇到了一些麻烦。如果设置了COMPUTE_FRAMES
标志ClassWriter
,我不会收到任何错误,但是代理会跳过某些类并且不会对其进行转换。经过一番研究,我发现造成这种情况的原因(很可能)是getCommonSuperClass
ClassWriter 的方法,它预先加载了类。
如果我不设置COMPUTE_FRAMES
标志,我会收到Expected stackmap frame at this location
无法解决的错误。
有人有解决这个问题的方法吗?
java - Java 11 类文件规范
我正在尝试查找 Java 11 的类文件规范,以便找出 11 和 8 LTS 版本之间的差异。
我发现它适用于 Java 版本 8、9 和 10,但不适用于 11:https ://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
我还在较新的 OpenJDK 站点上尝试过:http: //openjdk.java.net/projects/jdk/11/spec/
java - 为什么只为 *const_n JVM 指令定义了这样的常量范围?
根据 JVM规范,有几条指令针对使用一组特定的常量进行了优化。谁能解释为什么只定义了这个常数范围?
- iconst_n:压入整数常量 n,0 ≤ n ≤ 5
- lconst_n:推长常量n,0≤n≤1
- fconst_n:推送浮点常量 n,0 ≤ n ≤ 2
- dconst_n:push double 常数 n,0 ≤ n ≤ 1
我认为这是由于使用这些常数的频率,但我找不到我的想法或任何其他有关它的信息的确认。
java - 使用“invokedynamic” - 引擎盖下发生了什么?
背景
我目前正在用 C# 编写一个 JVM,纯粹是为了学术目的(将来可能会构建一个混合的 .NET 和 Java/Scala 应用程序)。
语境
我编写了简单的JAVA类:
并将其编译成test.class
. 当我用我的反编译器(我作为 JVM 的一部分编写的)反编译它时,我看到了这个方法的以下说明:
在常量池中查看 index 处的常量时2
,我看到一个 InvokeDynamic-Constant 条目,其中包含以下数据:
我想这是有道理的(我更像是 .NET 用户而不是 JAVA 用户)。
hello_world
使用参数执行我的方法时1
,在执行之前我有以下堆栈invokedynamic 2
:
问题
我的问题是:我该如何使用invokedynamic
?
我无法解析该方法makeConcatWithConstants
,因为 InvokeDynamic-Constant 没有给我任何提示,makeConcatWithConstants
可能位于何处(请参阅文档)。
堆栈也不包含对堆的引用,指示该方法makeConcatWithConstants
可以与哪个实例类型相关联。
我通读了invokedynamic
文档,但我不明白(也许我被 .NET-Framework 严重“损坏”了)。
有人可以给我举一些例子,说明在执行这三个指令时 JVM 引擎盖下发生了什么?(被调用者invokedynamic
期望什么等)?
我已经invokestatic
在我的 JVM 中实现了……但我目前无法理解invokedynamic
。
java - 构造函数字节码
ASM 指南讨论了构造函数:
Bean 类还有一个由编译器生成的默认公共构造函数,因为程序员没有定义显式构造函数。此默认公共构造函数生成为
Bean() { super(); }
. 此构造函数的字节码如下:第一条指令压
this
入操作数堆栈。第二条指令从堆栈中弹出这个值,并调用类中<init>
定义的方法Object
。这对应于super()
调用,即对超类的构造函数的调用Object
。您可以在这里看到,构造函数在编译类和源类中的命名不同:在编译类中它们总是命名为<init>
,而在源类中它们具有定义它们的类的名称。最后最后一条指令返回给调用者。
this
在构造函数的第一条指令之前,JVM 已经知道的值如何?
java - ASM:visitLabel 生成太多标签和 nop 指令
ASM 文档说标签代表一个基本块,它是控制图中的一个节点。所以我visitLabel
在这个简单的例子上测试了这个方法:
对于该visitLabel
方法,我使用本机 API: 对其进行检测setID(int id)
,其中 id 是增量的。在此示例中,CFG 应具有 3 个节点:一个位于开头,一个用于 if 语句的每个分支。所以我希望setID
会在 3 个位置被调用。但是,它被调用了5次,并且有很多nop
指令。有人可以为我解释为什么吗?
这是上述程序的检测字节码。
我不明白为什么label
每条istore
指令前都有一个。没有分支使其成为 CFG 中的新节点。