我正在开发一个带有 ASM 的 Java 检测引擎,有一种情况是评估堆栈在顶部有一个特定的值,我想在现有值之前插入一个ref(这是getstatic的结果)。即考虑只有一个值的堆栈: ,然后在getstatic 之后我希望堆栈变成这样:。value ->ref, value ->
要执行此行为,我必须插入以下字节码:getsatic和swap。使用 ASM 我会做类似的事情(考虑mv类型MethodVisitor):
mv.visitFieldInsn(Opcodes.GETSTATIC, ...);
mv.visitInsn(Opcodes.SWAP);
Run Code Online (Sandbox Code Playgroud)
问题是交换字节码不支持long和double值。所以上面的代码适用于单个单词类型,但它不适用于long和double类型。
是否有任何简单的解决方案可以解决long和double类型的问题并且不需要辅助本地值?
好吧,我正在阅读ASM4字节码库中的PDF教程/文档/书籍(如果你愿意的话).我正在尝试这些例子并通过阅读,实际输入代码,执行,然后从输出中学习来学习.我遇到了这个部分:
public class ClassPrinter extends ClassVisitor {
public ClassPrinter() {
super(ASM4);
}
Run Code Online (Sandbox Code Playgroud)
链接在这里: http://download.forge.objectweb.org/asm/asm4-guide.pdf
我无法弄清楚在超级中传递什么.我的IDE也不是很有帮助.
我正在使用 ASM 3.1 生成一个虚拟类。它只有一个简单的构造函数,没有其他方法:
public class TestAsm {
public static void main(String... args) throws Throwable {
ClassWriter sw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
sw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "test/SubCls", null, "test/SuperCls", null);
sw.visitField(Opcodes.ACC_PUBLIC, "i", "I", null, null);
MethodVisitor mv = sw.visitMethod(0, "<init>", "()V", null, null);
// mv.visitMaxs(2, 1);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "test/SuperCls", "<init>", "()V");
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitInsn(Opcodes.ICONST_2);
mv.visitFieldInsn(Opcodes.PUTFIELD, "test/SubCls", "i", "I");
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
sw.visitEnd();
byte[] cls = sw.toByteArray();
FileOutputStream fos = new FileOutputStream("bin/test/SubCls.class");
fos.write(cls);
fos.close();
SuperCls o = (SuperCls) Class.forName("test.SubCls").newInstance(); …Run Code Online (Sandbox Code Playgroud) 如何检查类的字节码(使用诸如ASM之类的东西)来了解哪些初始值传递给方法?
例如:给定一些将值互相传递的方法:
void m1(Object o) {
Object v = o;
m2(v);
m2("box");
}
void m2(Object o) {
Object v = o;
m3(x);
}
void m3(Object o) {
}
Run Code Online (Sandbox Code Playgroud)
还有一些方法调用,都在同一个类中定义:
{
Object foo = "foo";
m1(foo);
m2("bar");
m3("baz");
}
Run Code Online (Sandbox Code Playgroud)
我怎么可以检查类的字节码得知m3将与值被称为4倍"foo","box","bar"和"baz"?
我目前正在编写自己的编译器,我正在尝试编译以下代码:
List[String] list = List("a", "b", "c", "d")
list stream map((String s) => s.toUpperCase())
System out println list
Run Code Online (Sandbox Code Playgroud)
编译器解析,链接或编译代码没有问题,但是当执行它时,JVM会抛出以下错误:
java.lang.VerifyError: Illegal type at constant pool entry 40 in class dyvil.test.Main
Exception Details:
Location:
dyvil/test/Main.main([Ljava/lang/String;)V @29: invokevirtual
Reason:
Constant pool index 40 is invalid
Bytecode:
...
Run Code Online (Sandbox Code Playgroud)
我试图用来javap找到问题,这是指令@29:
29: invokevirtual #40 // InterfaceMethod java/util/Collection.stream:()Ljava/util/stream/Stream;
Run Code Online (Sandbox Code Playgroud)
并且常量池中的条目(也使用javap):
#37 = Utf8 stream
#38 = Utf8 ()Ljava/util/stream/Stream;
#39 = NameAndType #37:#38 // stream:()Ljava/util/stream/Stream;
#40 = InterfaceMethodref #36.#39 // java/util/Collection.stream:()Ljava/util/stream/Stream;
Run Code Online (Sandbox Code Playgroud)
使用Eclipse类文件查看器打开类时, …
使用ASM 5.0.4,我试图找到具有特定注释的类的字段和方法。我喜欢避免加载类而不用担心依赖关系。到目前为止,我无法弄清楚如何使用这种方法获取字段/方法注释:
class AnnotationScanner extends ClassVisitor{
public AnnotationVisitor visitAnnotation(String desc, boolean visible){
System.out.println("visitAnnotation: desc="+desc+" visible="+visible);
return super.visitAnnotation(desc,visible);
}
public void visitAttribute(Attribute attr){
System.out.println("visitAttribute: attr="+attr);
super.visitAttribute(attr);
}
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value){
System.out.println("visitField: access="+access+" name="+name+" desc="+desc+" signature="+signature+" value="+value);
return super.visitField(access,name,desc,signature,value);
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions){
System.out.println("visitMethod: access="+access+" name="+name+" desc="+desc+" signature="+signature+" exceptions="+exceptions);
return super.visitMethod(access,name,desc,signature,exceptions);
}
public static void main(String[] args) throws Exception{
for (String arg : …Run Code Online (Sandbox Code Playgroud) 我想if在特定行上更新现有类中的语句而不更改整个方法.
这是目标代码(类,方法和一些代码的名称已更改,因为它们不相关):
public class Target extends Something {
public Target(){
super();
//some code...
}
public Result targetMethod(Data firstPar, Data secondPar){
if(someStatement()) {
return Result.FAIL;
} else {
if(firstPar.check()){ //here is the line I want to change
firstPar.doSomething()
}
secondPar.doSomething();
return Result.SUCCESS;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这段代码中我想改成if(firstPar.check())这样的东西:
if(firstPar.check() && !Utilities.someOtherCheck(firstPar, secondPar))
Run Code Online (Sandbox Code Playgroud)
这是我试图解决这个问题的方法:
ClassNode node = new ClassNode();
ClassReader reader = new ClassReader(bytes); //bytes - original target class
reader.accept(node, 0);
ClassWriter cw = new ClassWriter(0);
node.accept(cw);
MethodVisitor visitor = …Run Code Online (Sandbox Code Playgroud) 我使用ASM更新类堆栈映射,但是当asm时getMergedType,发生以下异常:
java.lang.RuntimeException:
java.io.IOException:找不到IntefaceImplA的资源。
如果在没有asm的情况下修改class方法,则效果很好。
我定义了两个接口A和B:IntefaceImplA和
IntefaceImplB。
我的环境源代码:
IntefaceA.java
public interface IntefaceA {
void inteface();
}
Run Code Online (Sandbox Code Playgroud)
IntefaceImplA.java
public class IntefaceImplA implements IntefaceA {
@Override
public void inteface() {
}
}
Run Code Online (Sandbox Code Playgroud)
IntefaceImplB.java
public class IntefaceImplB implements IntefaceA {
@Override
public void inteface() {
}
}
Run Code Online (Sandbox Code Playgroud)
Test.java
public class Test {
public IntefaceA getImpl(boolean b) {
IntefaceA a = b ? new IntefaceImplA() : new IntefaceImplB();
return a;
}
Run Code Online (Sandbox Code Playgroud)
}
Main.java
public class Main {
public static void …Run Code Online (Sandbox Code Playgroud) 我有一个旧库(大约 2005 年),它执行字节码操作,但不涉及堆栈图。因此,我的 jvm (java 8) 抱怨它们是无效的类。规避错误的唯一方法是使用-noverify. 但这对我来说不是一个长期的解决方案。
在类已经生成之后,有什么办法可以重新生成堆栈映射吗?我看到ClassWriter该类有一个选项来重新生成堆栈映射,但我不确定如何读取字节类并重写一个新的。那可行吗?
例如,如果将int变量a和b存储在局部变量1和2中,则此代码将进行计算this.f(3+b*a)。(此指针存储在变量0中)
iload_1
aload_0
icons_3
iload_1
iload_1
imul
iadd
invokevirtual #4
Run Code Online (Sandbox Code Playgroud)
#4站在这里代表什么?