说我有一个这样的课:
public class Example{
private String secret = "Secret String";
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能添加一个getter来返回这个字符串(没有使用反射),所以我想以某种方式添加它
public String getSecret(){
return secret;
}
Run Code Online (Sandbox Code Playgroud) 我对一个不应该为null的变量有一个奇怪的java.lang.NullPointerException.
Object[] params = new Object[10];
if (param1 != null)
params[0] = param1;
Run Code Online (Sandbox Code Playgroud)
param1作为方法参数给出,它可以为null.通常,当影响param1到params [0]时,它不为null(否则它不会传递if语句).
这是错误(第144行是"params [0] = param1;"):
Exception in thread "Jalen Agent" java.lang.NullPointerException
at jalen.MethodStats.onMethodEntry(MethodStats.java:144)
at hanoi.TowersOfHanoi.solveHanoi(TowersOfHanoi.java)
at hanoi.TowersOfHanoi.main(TowersOfHanoi.java:29)
Run Code Online (Sandbox Code Playgroud)
以下是发生异常的方法的完整代码:
public static void onMethodEntry(int id, String className, String methodName, Object param1, Object param2, Object param3, Object param4, Object param5) {
synchronized (globalLock) {
Object[] params = new Object[10];
if (param1 != null)
params[0] = param1;
if (param2 != null)
params[1] = param2;
if (param3 != null)
params[2] = …Run Code Online (Sandbox Code Playgroud) 如何使用ASM库将此代码插入Java类文件中的方法?
long MEGABYTE = 1024L * 1024L;
Runtime runtime = Runtime.getRuntime();
runtime.gc();
long memory = runtime.totalMemory() - runtime.freeMemory();
double memoryUsage=(double)memory/MEGABYTE;
Run Code Online (Sandbox Code Playgroud) 我想用新内容替换方法体(sample.class:sayHello方法),然后执行sample.class.原来的sayHelo声明是:
public int sayHello(String args){
}
Run Code Online (Sandbox Code Playgroud)
我想修改它的主体:
System.out.println("sxu says: hello world!");
return 1;
Run Code Online (Sandbox Code Playgroud)
但是样例执行结果抛出异常:
Exception in thread "main" java.lang.VerifyError: Operand stack overflow
Exception Details:
Location:
code/sxu/demo/data/sample.sayHello(Ljava/lang/String;)I @4: ldc
Reason:
Exceeded max stack size.
Current Frame:
bci: @4
flags: { }
locals: { 'code/sxu/demo/data/sample', 'java/lang/String' }
stack: { 'code/sxu/demo/data/sample', 'java/io/PrintStream' }
Bytecode:
0000000: 2ab2 0028 122a b600 1704 acb2 0028 2bb6
0000010: 0017 04ac
Run Code Online (Sandbox Code Playgroud)
我使用asm工具,我的代码中有三个java类:
public class Adapt extends ClassLoader {
@Override
protected synchronized Class<?> loadClass(final String name,
final boolean resolve) …Run Code Online (Sandbox Code Playgroud) 我使用ASM库生成字节码,并且方法的"最大堆栈大小"将自动计算.在运行期间,我发现此值(最大堆栈大小)不正确.
我的源代码是:
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
....
MethodType initType = MethodType.methodType(void.class, clsList);
mv = cw.visitMethod(ACC_PUBLIC, "<init>", initType.toMethodDescriptorString(), null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/invoke/BaseTemplate", "<init>", "()V", false);
for(int i=0; i< list.size(); i++){
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1+i);
mv.visitFieldInsn(PUTFIELD, className, list.get(i).name(), Utils.getFieldDesc(list.get(i).type()));
}
mv.visitInsn(RETURN);
//mv.visitMaxs(2, 4); //Verify succeeds if uncomment this line.
mv.visitEnd();
....
//Verify generated code before class loading..
PrintWriter pw = new PrintWriter(System.out);
CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), true, pw);
Class<?> expClass =defineClass(..);
Run Code Online (Sandbox Code Playgroud)
上面的代码将生成字节码:
Classfile /C:/temp/TGWD.class
Last modified Mar 11, 2015; size …Run Code Online (Sandbox Code Playgroud) JVM有两条指令:( bipush操作数值应介于Byte.MIN_VALUE和之间Byte.MAX_VALUE.)和sipush(操作数值应介于Short.MIN_VALUE和之间Short.MAX_VALUE).相应地,MethodVisitorASM中提供API来操作这两个指令:
public void visitIntInsn(int opcode, int operand)
Run Code Online (Sandbox Code Playgroud)
因此,如何访问ASM中的其他非字节(短)基元?例如,原语long,double,int,boolean,和float数据?这看起来很奇怪,这些数据被封装为Long,Double,Integer.
给定一个任意Class实例,包括一个运行时生成的实例(.class磁盘上没有文件),有没有办法获取类字节?
我正在创建一个基于 ASM 的实用程序来动态生成类。我需要做的一件事是生成一个具有泛型类型作为参数的方法签名。例如
public void setValue(List<String> value) {...}
Run Code Online (Sandbox Code Playgroud)
问题是如何获得List<String>使用 ASM 库的描述符。我知道有一个实用方法asm.Type.getDescriptor(Class),我想知道有没有类似的方法getDescriptor(java.lang.reflect.Type),或者我该如何实现?
谢谢...绿色
比方说我有一个
class Foo(){
public final static int bar = -1;
}
Run Code Online (Sandbox Code Playgroud)
反汇编的字节码看起来像这样
super public class Foo
version 51:0
{
public static final Field bar:I = int -1;
public Method "<init>":"()V"
stack 1 locals 1
{
aload_0;
invokespecial Method java/lang/Object."<init>":"()V";
return;
}
} // end Class Foo
Run Code Online (Sandbox Code Playgroud)
是的,这让我感到惊讶.我本来期望有一个<clinit>包含赋值的方法bar,然后我可以替换它.(当我删除final修饰符时会发生这种情况.)
如何更改final字段的值?我该怎么做?
我已经从这篇文章中了解了如何在运行时使用ASM操作类。
但是我还有一个关于如何修改常量池的问题。以下是我要修改的示例Java程序
主jar文件:
public class test {
private static final String a = "Hello World";
private static final String b = "ASM is awasome";
public static void main(String[] args) {
int x = 10;
int y = 25;
int z = x * y;
System.out.println(a);
System.out.println(z);
System.out.println(b);
}
}
Run Code Online (Sandbox Code Playgroud)
我想将变量a从修改"Hello World"为"Multiply Of x*y is: "
我的特工班
import java.lang.instrument.*;
import java.security.ProtectionDomain;
import org.objectweb.asm.*;
public class ExampleAgent implements ClassFileTransformer {
private static final String TRANSFORM_CLASS …Run Code Online (Sandbox Code Playgroud)