类加载机制与JVM -Xverify参数关系

问题引申

使用javassist 动态生成了一个类,通过IDEA运行没有任何问题,但是通过IDEA JUnit运行则报VerifyError异常。

案发现场

代码如下:

//模拟代码0
public interface SharpHelper {

    Object run(String group, String name,int timeout, Callable callable);
    Object run(String group,int timeout,Callable callable);
}

//模拟代码1
public interface AppleService {
    String get(String value);
}

//模拟代码2
public class C1 implements Callable{

    private AppleService target;

	public Object call() throws Exception {  
		 java.lang.String result = null;  
		 result = target.get(this.args0);  
		 return result;  
	}

	public void setTarget(AppleService target) {  
		this.target = target;  
	} 

	public void setParam(java.lang.String args0) { 
		this.args0 = args0; 
	}
}

//模拟代码3
public class C2 implements AppleService {
	private AppleService target;
	@Autowired
	private SharpHelper sharp;
	
	public java.lang.String get(String args0){  
		try { 
			C1 callable = new C1();  
			callable.setTarget(this.target);  
			callable.setParam(args0);  


			//return (java.lang.String)sharp.run("goods","",10000,callable); 

            //在使用 javassist 3.27.0-GA 编译可以通过,并且正常运行,当然这样的代码是不对的
            //但是也正常运行了,
            return sharp.run("goods","",10000,callable); 
		} catch (Exception e) {  
			throw e;  
		}  
	}
	
}

但是使用JUnit运行,则无法启动,提示VerifyError异常。

通过类加载机制,原因是触发了类加载机制中的校验 原文链接:类加载机制-深入理解jvm - 简书,错误的源代码无法校验通过。 原文链接:类加载机制-深入理解jvm - 简书

图片来自原文内

  

通过查阅IDEA 启动项目后的JVM参数(通过jdk工具 jps)

执行命令:jps -v

16580 ProductApplication

-XX:TieredStopAtLevel=1

-Xverify:none

-Dspring.output.ansi.enabled=always

-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.1.3\lib\idea_rt.jar=49400:C:\P
rogram Files\JetBrains\IntelliJ IDEA 2021.1.3\bin

-Dcom.sun.management.jmxremote

-Dspring.jmx.enabled=true

-Dspring.liveBeansView.mbeanDomain

-Dspring.application.admin.enabled=true

-Dfile.encoding=UTF-8

参数释义

-Xverify[:<option>]

如果不使用任何参数,那么将启用验证器,这是缺省值。 因此,如果单独使用而不带任何参数,如 -Xverify,那么此选项将不执行任何操作。可选参数如下所示:

  • all - 启用最完整的验证
  • none - 禁用验证器
  • remote - 对远程装入的类启用严格的类装入检查

缺省情况下,验证器处于开启状态,必须针对所有生产服务器启用验证器。不支持在关闭验证器的情况下运行。 如果遇到问题,并且使用 -Xverify:none 关闭了验证器,那么请除去此选项并尝试重现问题。

查阅JUnit下的JVM 参数

5840 JUnitStarter

-agentlib:jdwp=transport=dt_socket,address=127.0.0.1:50452,suspend=y,server=n

-ea

-Didea.test.cyclic.buffer.size=1048576

-javaagent:C:\Users\jiangj\AppData\Local\JetBra
ins\IntelliJIdea2021.1\captureAgent\debugger-agent.jar

-Dfile.encoding=UTF-8 

没有发现-Xverify参数的定义,那么默认将启用检验,所以错误的源代码无法运行,会抛出VerifyError异常。

解决方案

1.Junit 下增加 JVM 参数 -noverify(强烈建议加最后) 关闭类的校验

2.书写正确的源代码(这个坑其实是BUG产生的)

疑惑

为什么错误的源代码在-Xverify:none下依然可以运行?

本人猜测:因为java关闭了类的校验,所以代码不严谨(例如类型不严谨)的问题就被略去了,JAVA本身实现一些特性靠的就是剑走偏锋(例如泛型)。只要运行时是能过关的,很多问题人们可能就也不会去追究了。

之前本人还遇到过,声明的变量为List<Student> 的集合。内部实际装载的是List<JSONObject>

运行也没问题,因为泛型擦除后所有List 内部都是Object。

当然这样的异常效果都是运行时才能得到(通过javassist骚操作),这个例子似乎好像可以解释,为什么源代码都有误,但是不影响运行,姑且这样信下去,直到有一天,产生新的认知。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值