首先纠正一个误区: 热部署不是我们在Eclipse里面修改了代码不用重启就可以持续调试. 详情可以参考上一篇博文: 热部署和"Hot Code Replace"的区别 http://flyfoxs.iteye.com/blog/2078863
热部署有一个缺陷,就是很容易导致内存泄露, 并且不是很容易从代码层次避免. 所以产品环境一般不推荐启用热部署.
JAVA里面经常遇到的内存泄露,是一个无用对象长期被引用导致无法被回收.这种情况只要注意集合对象,基本就能避免大部分问题.这个也是可以测试,或者分析内存对象也能发现.
但是热部署也会导致内存泄露,这个问题却很少被引起注意,因为它并不是很容易重现.并且相比前一种内存泄露,并不是很好理解.下面来对这种内存泄露来做一个简单分析.
- 场景分析:
JVM只提供了加载Class的方法,没有提供卸载的方法.所以针对这种情况就需要使用新的ClassLoader来重新加载新的Class来实现热部署. 大部分情况下旧的ClassLoader及所Loader的对象就会形成一个孤岛,稍后就会被回收.
但是事情不是绝对的,如果恰巧有别的ClassLoader加载了一个对象,并且这个对象引用了孤岛中的某个对象,那么孤岛将不再是孤岛,这个时候内存泄露就会发生了.比如Log4j和热部署加一块,就可能会出现内存泄露
- 场景简化:
使用Tomcat来观察内存泄露比较复杂,既然分析出了是热部署导致的内存泄露.那么我们通过自己实现类加载器的热部署应该同样也可以观察的到内存泄露.
具体的方法就是:
1)通过实现一个Classloader,加载指定的Class并实例化,然后关联到LinkedList上面.
2)监控指定Class的变化,如果有变化就new一个新的ClassLoader对象,然后重新加载Class并实例化对象,然后关联到LinkedList上面.
3)观察新旧ClassLoader生成出来的对象,是否可被垃圾回收.如果不能垃圾回收,在Tomcat进行热部署也会有同样的事情了.
- 代码示例
1)如果MonitorHotSwap.list.size()>1则说明有了内存泄露,详情大家可以看下面的代码, 也可以下载附件自己去运行一下.附件下载地址
2)需要修改Hot类来触发重新加载Class
3)需要根据你自己的项目路径,修改HotSwapURLClassLoader里面的属性值
4)主要代码来自于下面的参考链接,根据需要进行了部分修改.
class MonitorHotSwap implements Runnable { // Hot就是用于修改,用来测试热加载 private String className = "classloader.Hot"; private Class hotClazz = null; private HotSwapURLClassLoader hotSwapCL = null; private List<Object> list = new LinkedList(); @Override public void run() { try { while (true) { initLoad(); Object hot = hotClazz.newInstance(); if(!isExisting(hot)){ list.add(hot); } Method m = hotClazz.getMethod("toString"); m.invoke(hot, null); // 打印出相关信息 System.out.println("========================================"); System.out.println("List size="+list.size()); // 每隔5秒重新加载一次 Thread.sleep(5000); } } catch (Exception e) { e.printStackTrace(); } } /** * 加载class */ void initLoad() throws Exception { hotSwapCL = HotSwapURLClassLoader.getClassLoader(); // 如果Hot类被修改了,那么会重新加载,hotClass也会返回新的 hotClazz = hotSwapCL.loadClass(className); } boolean isExisting(Object obj){ for(Object tempObj : list){ if(tempObj.getClass().getClassLoader().equals(obj.getClass().getClassLoader())){ return true; } } return false; }
- 解决方案:
注册一个Listener, 解除当前WebappClassloader加载的对象和高层ClassLoader加载对象的关联关系. 这样当War报Destory的时候, 可以使当前WebappClassloader加载对象形成一个真正的孤岛,等待回收.
注:
同一个ClassLoader(并不仅仅指的是同一个Class,而是同一个实例),具体来说就是如果一个JVM里面, 如果new了多个ClassLoader,那么他们是不同的ClassLoader.这样当他们Loader相同Class时,这些生成的实例,虽然包名,类名想等,但是却不可能equals.
JSP如何实现热部署
http://www.linuxidc.com/Linux/2013-05/83816.htm
class卸载、热替换和Tomcat的热部署的分析(有示例)
http://www.blogjava.net/heavensay/archive/2012/11/07/389685.html
JVM GC垃圾回收和ClassLoader类加载器之间的微妙关系
http://blog.csdn.net/runanli/article/details/2972361
相关推荐
myeclipse 插件热部署 jrebel6.5 亲测可用,资源下载到磁盘,然后打开myeclipse 路径为:Windows ---> Perferences --> MyEclipse -->Servers -->Tomcat --> Tomcat 7.x -->JDK 配置jvm参数: -...
主要介绍了Java基于自定义类加载器实现热部署过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
-noverify -javaagent:D:\myeclipse\jar\jrebel6.5.0\jrebel.jar -Drebel.dirs=${project_loc}\WEB-INF\classes -Drebel.spring_plugin=true -Drebel.struts2-plugin=true -Drebel.hibernate_plugin=true -Xms256M -...
这是一个支持热部署的软件,在Java项目中修改Java代码不需在重启服务器。一个很实用的Java编程软件
jrebel-idea-热部署ar包.zip。 IDEA热部署插件,修改代码可不用重启项目,方便调试。
jrebel-idea-热部署软件.zip。 IDEA热部署插件jrebel,修改代码可不用重启项目
springboot+mybatis+thymeleaf 热部署 java 热部署页面访问
有没有在为修改java代码 反复重启tomcat而烦恼 下载热部署一切不成问题。内容:1.热部署 2.分给myeclipse 1g内存
java热部署
java类加载修改源码皮诺克 Pinoc 是一个新颖的库,用于对 ...为了避免Java类加载器带来的麻烦,Pinoc没有采用Java类加载器来加载和执行对原有方法的替换或修改。 因此,原始方法的替换或修改不是用
在 Java 开发领域,热部署一直是一个难以解决的问题,目前的 Java 虚拟机只能实现方法体的修改热部署,对于整个类的结构修改,仍然需要重启虚拟机,对类重新加载才能完成更新操作。对于某些大型的应用来说,每次的...
Java 自定义ClassLoader 实现类的热替换核心代码
热部署工具
高级Java人才培训专家-012_项目部署_持续集成
idea热部署(更新代码不用重启tomcat).docx idea热部署(更新代码不用重启tomcat).docx
java 实现xxl-job安装与部署
java运维 ,微服务平台使用Docker compose部署案例,并附文件代码及注意事项。
java毕业设计项目叮当书城项目|叮当书城项目部署代码视频教程带源码(|java练手项目) 项目文件代码介绍部分内容: 1、首先就是src下面的java文件,存放的是我们后端需要的文件 2、 然后下面的bean文件,里面...
类加载分析工具,在应用部署后,可找出是哪个类呗加载了,在那个目录或者jar中,内部资料