所以基本上我试图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
目前,我参与了一个大型遗留项目,其中包含许多巨大的类和生成的代码。我希望找到所有字节码长度大于 8000 字节的方法(因为 OOTB java 不会优化它)。
我找到了这样的手动方式:How much bytes of bytecode has a certain method in Java? ,但是我的目标是自动扫描许多文件。
我尝试使用 jboss-javassist,但据我所知,获取字节码长度仅在类级别可用。
我目前正在用 C# 编写 JVM,纯粹出于学术目的(也许将来会构建混合的 .NET 和 Java/Scala 应用程序)。
我写了一个简单的JAVA类:
public class test
{
public static String hello_world(int i)
{
return "Hello " + i + " World!";
}
}
Run Code Online (Sandbox Code Playgroud)
并将其编译成test.class. 当我使用反编译器(我将其编写为 JVM 的一部分)对其进行反编译时,我看到此方法的以下说明:
iload_0
invokedynamic 2
areturn
Run Code Online (Sandbox Code Playgroud)
当在常量池中查找索引处的常量时2,我看到一个包含以下数据的 InvokeDynamic-Constant 条目:
makeConcatWithConstants : (I)Ljava/lang/String;
Run Code Online (Sandbox Code Playgroud)
我想这是有道理的(我更像是 .NET 用户而不是 JAVA 用户)。
hello_world当使用参数执行我的方法时1,在执行之前我有以下堆栈invokedynamic 2:
----TOP---
0x00000001
--BOTTOM--
Run Code Online (Sandbox Code Playgroud)
我的问题是:我该如何使用invokedynamic?
我无法解析该方法makeConcatWithConstants,因为 InvokeDynamic-Constant 没有给我任何makeConcatWithConstants可能位于何处的提示(请参阅文档)。 …
该ASM引导谈到构造函数:
Run Code Online (Sandbox Code Playgroud)package pkg; public class Bean { private int f; public int getF() { return this.f; } public void setF(int f) { this.f = f; } }Bean类还具有由编译器生成的默认公共构造函数,因为程序员没有定义任何显式构造函数。此默认的公共构造函数生成为
Bean() { super(); }。该构造函数的字节码如下:Run Code Online (Sandbox Code Playgroud)ALOAD 0 INVOKESPECIAL java/lang/Object <init> ()V RETURN第一条指令压
this入操作数堆栈。第二条指令从堆栈中弹出该值,并调用类中<init>定义的方法Object。这对应于super()调用,即对超类的构造函数的调用Object。您可以在此处看到,在编译类和源类中,构造函数的名称不同:在编译类中,它们总是命名为<init>,而在源类中,它们具有定义它们的类的名称。最后,最后一条指令返回给调用者。
this在构造函数的第一条指令之前,JVM已知的值如何?
尝试对服务器应用程序启动进行故障排除时,我在旧版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-很抱歉使每个人都对具有不同返回值的方法的模棱两可的命名感到困惑,这是一个复制粘贴问题,因为代码位于没有直接访问该站点的远程计算机上。
我编译了以下方法:
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)
我编写了 …
给定一个任意Class实例,包括一个运行时生成的实例(.class磁盘上没有文件),有没有办法获取类字节?
我正在为 Java 创建一个静态分析工具,并且有一些有关我正在分析的程序的信息,如果我可以从文件中的字节码中获取这些信息,将更容易获得这些信息.class。
我不关心类文件中可能存在的每一条指令。例如,我可能只需要看看是否有任何getfield说明。
问题是,由于每条指令都有一个可变的长度,似乎在一般情况下,我需要(在我的代码中)指定每个操作码的长度,然后才能确定(例如)指令的开始和getfield结束位置。
对于其他一些指令集(例如x86),有一些规则,例如“任何低于 0x0F 的操作码都是 1 个字节,任何等于或大于 0x0F 的操作码都是两个字节。”
Java字节码指令中有类似这样方便的模式吗?
我正在查看一些反编译代码并看到.getClass();,即没有对其返回值进行任何处理。
public String forLocale(Locale locale, String keyword) {
Stream var10000 = getLocaleMappingList(locale, this.getSupportedLocales());
Map var10001 = this.translations;
var10001.getClass();
Map<String, String> translation = (Map)var10000.map(var10001::get).filter((m) -> {
return m.containsKey(keyword);
}).findFirst().orElse(this.translations.get(FALLBACK));
Preconditions.checkState(translation.containsKey(keyword), keyword + " is not a valid translation key");
return (String)translation.get(keyword);
}
Run Code Online (Sandbox Code Playgroud)
那是做什么用的?原来的代码是这样的吗?(到目前为止,我还没有看到反编译代码的实例至少在行方面与源代码不匹配。)
这有点像一个断言,但是通过这样做而不是让事情出错,可以实现var10001::get什么?或者更多的是关于性能?
更新
这是字节码。很酷的事情来学习如何做!
// access flags 0x1
public forLocale(Ljava/util/Locale;Ljava/lang/String;)Ljava/lang/String;
L0
LINENUMBER 184 L0
ALOAD 1
ALOAD 0
INVOKEVIRTUAL com/spotify/i18n/Translations.getSupportedLocales ()Ljava/util/Set;
INVOKESTATIC com/spotify/i18n/Translations.getLocaleMappingList (Ljava/util/Locale;Ljava/util/Collection;)Ljava/util/stream/Stream;
ALOAD 0
GETFIELD com/spotify/i18n/Translations.translations : Ljava/util/Map;
DUP …Run Code Online (Sandbox Code Playgroud) 我正在将一种简单的语言编译成 JVM 字节码,并且在 Java 对象方法调用方面存在一些问题。验证器给出以下错误
java.lang.VerifyError: (class: Test_1, method: main signature: ()V) Expecting to find object/array on stack
以下是 IntelliJ 从我的字节码生成的 Java 源代码
import java.util.ArrayList;
public final class Test_1 {
public static void main() {
ArrayList var1 = new ArrayList();
var1.add(19);
int var2 = (Integer)var1.get(0);
}
}
Run Code Online (Sandbox Code Playgroud)
这正是我想要做的。创建一个 ArrayList,分配一个值并从中读取。上面的代码对我来说看起来像是一个有效的 Java 代码。
下面是我的字节码
{
public static void main();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=0
0: new #9 // class java/util/ArrayList
3: dup
4: invokespecial #12 // Method java/util/ArrayList."<init>":()V …Run Code Online (Sandbox Code Playgroud)