使用类似ASMor 的库cglib,有没有办法在每次设置类字段的值时将字节码指令添加到类中以执行代码?
例如,假设我有这个类:
public class Person
{
bool dirty;
public String name;
public Date birthDate;
public double salary;
}
Run Code Online (Sandbox Code Playgroud)
假设一段代码包含以下行:
person.name = "Joe";
我希望拦截此指令,以便将dirty标志设置为true.我知道这对于setter方法是可行的person.setName (“Joe”)- 因为类方法可以通过字节码操作来修改,但我想对字段做同样的事情.
这是可能的,如果是的话,怎么样?
编辑
我想避免修改访问类的代码部分,我正在寻找一种方法来将拦截代码作为Person类的一部分.是否存在用于字段访问的伪方法,类似于Python类中的属性?
我在网上找到的所有引用都说字节码可以在运行时修改,但我似乎没有找到修改后的字节码是否可以替换原始字节码.
这样原始字节码可以替换一次,其余时间使用增强后的.
我有很多真/假结果保存为long[]数组中的位.我确实拥有大量的这些(数百万和数百万的长).
例如,假设我只有五个结果,我会:
+----- condition 5 is true
|
|+---- condition 4 is false
||
||+--- condition 3 is true
|||
|||+-- condition 2 is true
||||
||||+- condition 1 is false
10110
Run Code Online (Sandbox Code Playgroud)
我也有一些树代表如下的语句:
condition1 AND (condition2 OR (condition3 AND condition 4))
Run Code Online (Sandbox Code Playgroud)
树很简单但很长.他们基本上看起来像这样(下面是过于简单化,只是为了表明我得到了什么):
class Node {
int operator();
List<Node> nodes;
int conditionNumber();
}
Run Code Online (Sandbox Code Playgroud)
基本上,Node是一个叶子,然后有一个条件号(匹配long []数组中的一个位)或者Node不是叶子,因此引用了几个子节点.
它们很简单,但它们允许表达复杂的布尔表达式.它很棒.
到目前为止一切都很好,一切都很好.但是我确实有一个问题:我需要评估很多表达式,确定它们是真还是假.基本上我需要对一个问题进行一些暴力计算,而这个问题除了暴力破解之外还没有比这更好的解决方案.
所以我需要走树然后回答,true或者false取决于树的内容和内容long[].
我需要优化的方法如下所示:
boolean solve( Node node, long[] trueorfalse ) {
...
}
Run Code Online (Sandbox Code Playgroud)
在第一次调用时,它node …
我想使用ASM将静态最终字段添加到.class文件中,源文件是
public class Example {
public Example(int code) {
this.code = code;
}
public int getCode() {
return code;
}
private final int code;
}
Run Code Online (Sandbox Code Playgroud)
并且生成的反编译类应该是这样的:
public class Example {
public static final Example FIRST = new Example(1);
public static final Example SECOND = new Example(2);
public Example(int code) {
this.code = code;
}
public int getCode() {
return code;
}
private final int code;
}
Run Code Online (Sandbox Code Playgroud)
作为结论,我想使用ASM将FIRST和SECOND常量添加到.class文件中,我该怎么办?
java assembly bytecode bytecode-manipulation java-bytecode-asm
我在使用Guava库运行一个简单的主程序时遇到了一些麻烦.
我已经使用我的代码从类中检测了类以获取方法参数:ASM中的Java方法参数值
问题是,虽然代码适用于小型项目(也就是河内之塔),但是使用Guava我有错误和例外.
特别是,在测试Joiner.join方法时,我有这个错误:
Exception in thread "Jalen Agent" java.lang.VerifyError: (class: com/google/common/base/Joiner, method: withKeyValueSeparator signature: (Ljava/lang/String;)Lcom/google/common/base/Joiner$MapJoiner;) Incompatible argument to function
at Main.joinBench(Main.java:42)
at Main.main(Main.java:20)
Run Code Online (Sandbox Code Playgroud)
当使用-noverify运行示例时,我有一个例外:
Exception in thread "Jalen Agent" java.lang.ArrayIndexOutOfBoundsException: 1
at com.google.common.base.Joiner.<init>(Joiner.java)
at com.google.common.base.Joiner.on(Joiner.java:71)
at Main.joinBench(Main.java:42)
at Main.main(Main.java:20)
Run Code Online (Sandbox Code Playgroud)
该方法的字节码是一致的:
public static com.google.common.base.Joiner on(java.lang.String);
Code:
0: bipush 1
2: anewarray #4 // class java/lang/Object
5: astore_1
6: aload_1
7: bipush 0
9: aload_0
10: aastore
11: ldc #20 // int 369
13: ldc #21 // String com/google/common/base/Joiner
15: …Run Code Online (Sandbox Code Playgroud) java bytecode bytecode-manipulation verifyerror java-bytecode-asm
在Java中,如何获取方法中使用的Fields?
基本上,这与.NET中的这个问题相同.我不想列出类中的字段,而是列出在类的给定方法中使用的字段.
例:
public class A {
int a;
int b;
public int bob(){
return a-b;
}
Run Code Online (Sandbox Code Playgroud)
我想得到这样的字段:
Fields[] fields = FieldReader.(A.class.getMethod("bob"));
Run Code Online (Sandbox Code Playgroud)
那样fields[0]=A.a和fields[1]=A.b
我没有找到任何使用标准反射的解决方案.你认为像ASM这样的字节码操作库是一种方法吗?
环境
我正在使用需要字节码检测的第三方库.执行字节码检测的工具需要一些描述文件,这些文件必须与编译的.class文件位于相同的文件夹结构中.这些文件只在编译时才需要.
问题
我以为gradle会将所有文件(资源和类)暂时放在同一个文件夹中,然后从该文件夹创建一个jar.但是在组装jar之前,gradle似乎有两个不同的资源和类文件位置.就像之前提到的第三方代码检测工具一样,需要在类文件结构中使用相同文件夹结构中的描述文件.
题
简单地说:我该如何解决这个问题?
思路
src/main/java.不是很"干净",但可能是一个解决方案.遗憾的是,gradle会忽略这些文件.我试图以某种方式包括它们,但还没有让它工作.我想将一些对象实例绑定到使用 Javassist 创建的类。这个对象是从某个来源读取的,数据是不知道的。
// Create the class.
CtClass subClass = pool.makeClass( fullName );
final CtClass superClass = pool.get( Foo.class.getName() );
subClass.setSuperclass( superClass );
// Add a static field containing the definition. // Probably unachievable.
final CtClass defClass = pool.get( SomeMetaData.class.getName() );
CtField defField = new CtField( defClass, "DEF", subClass );
defField.setModifiers( Modifier.STATIC );
subClass.addField( CtField.Initializer.??? );
return subClass.toClass();
Run Code Online (Sandbox Code Playgroud)
但是当我检查 API 时,Javassist 似乎创建了一个真正的字节码,它根据“调用这个”或“实例化那个”或“使用这个常量”来存储初始化。
有没有办法让 Javassist 添加一个静态字段,该字段已初始化为运行时给定的现有实例?
我一直试图通过玩转 ASM 中的跳转来了解堆栈映射框架在 Java 中的工作原理。我创建了一个简单的方法来尝试一些东西:(用 Krakatau 拆卸):
L0: ldc 'hello'
L2: astore_1
L3: getstatic Field java/lang/System out Ljava/io/PrintStream;
L6: new java/lang/StringBuilder
L9: dup
L10: invokespecial Method java/lang/StringBuilder <init> ()V
L13: ldc 'concat1'
L15: invokevirtual Method java/lang/StringBuilder append (Ljava/lang/String;)Ljava/lang/StringBuilder;
L18: aload_1
L19: invokevirtual Method java/lang/StringBuilder append (Ljava/lang/String;)Ljava/lang/StringBuilder;
L22: invokevirtual Method java/lang/StringBuilder toString ()Ljava/lang/String;
L25: invokevirtual Method java/io/PrintStream println (Ljava/lang/String;)V
L28: getstatic Field java/lang/System out Ljava/io/PrintStream;
L31: new java/lang/StringBuilder
L34: dup
L35: invokespecial Method java/lang/StringBuilder <init> ()V
L38: ldc 'concat2'
L40: invokevirtual …Run Code Online (Sandbox Code Playgroud) Java asm - 如何创建仅更改类名的类的克隆?
我知道有一种简单的方法可以使用 asm SimpleRemapper修改类名,但我只想更改外部类名,而不修改方法中使用的类名。(请参阅下面的示例)
基本上如果我有目标班级
public class Target {
public Target clone(...) ...
public int compare(another: Target) ...
}
Run Code Online (Sandbox Code Playgroud)
我只是想创建一个看起来像这样的克隆:
public class ClonedTarget {
public Target clone(...) ...
public int compare(another: Target) ...
}
Run Code Online (Sandbox Code Playgroud)
(请注意, 的返回类型clone和 arg 类型compare没有改变。这是针对我的用例而设计的)。
java bytecode bytecode-manipulation java-bytecode-asm java-8
java ×10
bytecode ×3
javassist ×2
assembly ×1
gradle ×1
java-8 ×1
jvm-bytecode ×1
optimization ×1
reflection ×1
static ×1
verifyerror ×1