我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。
扫描二维码或搜索下图红色VX号,加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。
推荐文章:Java 面试知识点解析;Mysql优化技巧(数据库设计、命名规范、索引优化
前言
让我们继续探秘 Java 热部署。在前文 探秘 Java 热部署二(Java agent premain)中,我们介绍了 Java agent premain。通过在main方法之前通过类似 AOP 的方式添加 premain 方法,我们可以在类加载之前做修改字节码的操作,无论是第一次加载,还是每次新的 ClassLoader 加载,都会经过 ClassFileTransformer 的 transform 方法,也就是说,都可以在这个方法中修改字节码,虽然他的方法名是 premain ,但是我们确实可以利用这个特性做这个事情。
在文章的最后,我们也提到了,虽然相比较在自定义类中修改字节码,premain 没有什么侵入性,对业务透明,但是美中不足的是,他还需要在启动的时候增加参数。
我们还提到了,premain 虽然可以热部署,但是还需要重新创建类加载器,虽然,这的确也符合 JVM 关于类的唯一性的定义。但是,有一种情况,如果使用的是系统类加载器,我们也无法创建新的ClassLoader对象。那么我们也就无法重新加载类了,怎么办呢?还好 Java 6 为我们提供了一种方法,也就是今天的主角 agentmain。
1. 什么是 agentmain?
和 premain 师出同门,我们知道,premain 只能在类加载之前修改字节码,类加载之后无能为力,只能通过重新创建ClassLoader 这种方式重新加载。而 agentmain 就是为了弥补这种缺点而诞生的。简而言之,agentmain 可以在类加载之后再次加载一个类,也就是重定义,你就可以通过在重定义的时候进行修改类了,甚至不需要创建新的类加载器,JVM 已经在内部对类进行了重定义(重定义的过程相当复杂)。
但是这种方式对类的修改是由限制的,对比原来的老类,由如下要求:
1.父类是同一个;
- 实习那的接口数也要相同;
- 类访问符必须一致;
- 字段数和字段名必须一致;
- 新增的方法必须是 private static/final 的;
- 可以删除修改方法;
可以看的出来,相比较重新创建类加载器,限制还