JavaRebel 关于 noverify 和 javaagent 参数的使用

一般情况下,使用 JavaRebel 时都配置两个 JVM 参数:-noverify 和 -javaagent
一、-javaagent 参数
这个参数是 JDK5 引入的,可以通过 java -h 查看其帮助信息
// 省略
-javaagent:<jarpath>[=<options>]
load Java programming language agent, see java.lang.instrument
// 省略

通过使用 -javaagent 参数,用户可以在执行 main 函数前执行指定 javaagent 包中的特定代码,甚至可以动态的修改替换类中代码。
javaagent 的代码与你的 main 方法在同一个 JVM 中运行,并被同一个 system classloader 装载,被同一的安全策略(security policy) 和上下文(context)所管理。

如何写一个 javaagent 程序呢?实现很简单,只需要在类中实现 premain 接口:
public static void premain(String agentArgs, Instrumentation inst)

例如可以动态将下面方法中的 true 改为 false

package testagent;
public class TestAgent {
public boolean isOK() {
return true;
}
public static void main(String[] args) {
System.out.println(new TestAgent().isOK());
}
}


package testagent;
import java.lang.instrument.Instrumentation;
public class MyTestAgent {
public static void premain(String agentArgs,Instrumentation inst) {
inst.addTransformer(new MyTestTransformer());
}
}


package testagent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class MyTestTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
if(!className.equals("testagent/TestAgent"))
return null;
for(int i=0; i<classfileBuffer.length; i++) {
if(classfileBuffer[i] == (byte)0x04
&& classfileBuffer[i+1] == (byte)0xAC) {
classfileBuffer[i] = (byte)0x03;
}
}
return classfileBuffer;
}
}

// 注意:提前创建 META-INF/MANIFEST.MF 文件
jar -cvfm myagent.jar META-INF/MANIFEST.MF testagent/MyTestAgent.class testagent/MyTestTransformer.class

其中的 MANIFEST.MF 的内容如下:
Manifest-Version: 1.0
Created-By: 1.6.0_16 (Sun Microsystems Inc.)
Premain-Class: testagent.MyTestAgent

而运行方法则如下:
java -javaagent:myagent.jar testagent.TestAgent

二、-noverify 参数
通过使用 -noverify 参数,关闭 Java 字节码的校验功能。
当 ClassLoader 加载的Java 字节码时,字节码首先接受校验器(verifier)的校验。校验器负责检查那些指令无法执行的明显的破坏性的操作。校验器执行的检查操作:
1、变量要在使用之前进行初始化。
2、方法调用与对象应用类型之间要匹配。
3、访问私有数据和方法的规则没有被违反。
4、对本地变量的访问都在运行时堆栈内。
5、运行时堆栈没有溢处。

下面实际演示一下,手动修改 class 文件前后的情况。测试类文件如下:

package testverify;
public class TestVerify {
public int test() {
int i = 0, j = 1;
return i+j;
}
public static void main(String[] args) {
System.out.println(new TestVerify().test());
}
}

执行: java testverify.TestVerify
结果:1

手动将十六进制代码 03 3C 04 3D 1B 1C 60 AC 部分 3D 改成 3C ,即从 istore_2 改为 istore_1 ,局部变量 1 被初始化两次,而局部变量 2 未被初始化。
执行:java testverify.TestVerify
结果:Exception in thread "main" java.lang.VerifyError: (class: testverify/TestVerify,
method: test signature: ()I) Accessing value from uninitialized register 2
Could not find the main class: testverify.TestVerify. Program will exit.

执行:java -noverify testverify.TestVerify
结果:1
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值