一 class的热替换

ClassLoader中重要的方法

loadClass
ClassLoader.loadClass(...) 是ClassLoader的入口点。当一个类没有指明用什么加载器加载的时候,JVM默认采用AppClassLoader加载器加载没有加载过的class,调用的方法的入口就是loadClass(…)。如果一个class被自定义的ClassLoader加载,那么JVM也会调用这个自定义的ClassLoader.loadClass(…)方法来加载class内部引用的一些别的class文件。重载这个方法,能实现自定义加载class的方式,抛弃双亲委托机制,但是即使不采用双亲委托机制,比如java.lang包中的相关类还是不能自定义一个同名的类来代替,主要因为JVM解析、验证class的时候,会进行相关判断。

defineClass
系统自带的ClassLoader,默认加载程序的是AppClassLoader,ClassLoader加载一个class,最终调用的是defineClass(…)方法,这时候就在想是否可以重复调用defineClass(…)方法加载同一个类(或者修改过),最后发现调用多次的话会有相关错误:

java.lang.LinkageError
attempted duplicate class definition

所以一个class被一个ClassLoader实例加载过的话,就不能再被这个ClassLoader实例再次加载(这里的加载指的是,调用了defileClass(…)放方法,重新加载字节码、解析、验证。)。而系统默认的AppClassLoader加载器,他们内部会缓存加载过的class,重新加载的话,就直接取缓存。所与对于热加载的话,只能重新创建一个ClassLoader,然后再去加载已经被加载过的class文件。

二 class卸载

在Java中class也是可以unload。JVM中class和Meta信息存放在PermGen space区域。如果加载的class文件很多,那么可能导致PermGen space区域空间溢出。引起:java.lang.OutOfMemoryErrorPermGen space. 对于有些Class我们可能只需要使用一次,就不再需要了,也可能我们修改了class文件,我们需要重新加载 newclass,那么oldclass就不再需要了。那么JVM怎么样才能卸载Class呢。

JVM中的Class只有满足以下三个条件,才能被GC回收,也就是该Class被卸载(unload):

  • 该类所有的实例都已经被GC。
  • 加载该类的ClassLoader实例已经被GC。
  • 该类的java.lang.Class对象没有在任何地方被引用。

GC的时机我们是不可控的,那么同样的我们对于Class的卸载也是不可控的。

1、有启动类加载器加载的类型在整个运行期间是不可能被卸载的(jvm和jls规范).
2、被系统类加载器和标准扩展类加载器加载的类型在运行期间不太可能被卸载,因为系统类加载器实例或者标准扩展类的实例基本上在整个运行期间总能直接或者间接的访问的到,其达到unreachable的可能性极小.(当然,在虚拟机快退出的时候可以,因为不管ClassLoader实例或者Class(java.lang.Class)实例也都是在堆中存在,同样遵循垃圾收集的规则).
3、被开发者自定义的类加载器实例加载的类型只有在很简单的上下文环境中才能被卸载,而且一般还要借助于强制调用虚拟机的垃圾收集功能才可以做到.可以预想,稍微复杂点的应用场景中(尤其很多时候,用户在开发自定义类加载器实例的时候采用缓存的策略以提高系统性能),被加载的类型在运行期间也是几乎不太可能被卸载的(至少卸载的时间是不确定的).

综合以上三点, 一个已经加载的类型被卸载的几率很小至少被卸载的时间是不确定的.同时,我们可以看的出来,开发者在开发代码时候,不应该对虚拟机的类型卸载做任何假设的前提下来实现系统中的特定功能.

三 Tomcat中关于类的加载与卸载

Tomcat中与其说有热加载,还不如说是热部署来的准确些。因为对于一个应用,其中class文件被修改过,那么Tomcat会先卸载这个应用(Context),然后重新加载这个应用,其中关键就在于自定义ClassLoader的应用。这里有篇文章很好的介绍了tomcat中对于ClassLoader的应用。

Tomcat启动的时候,ClassLoader加载的流程:

1 Tomcat启动的时候,用system classloader即AppClassLoader加载{catalina.home}/bin里面的jar包,也就是tomcat启动相关的jar包。 2 Tomcat启动类Bootstrap中有3个classloader属性,catalinaLoader、commonLoader、sharedLoader在Tomcat7中默认他们初始化都为同一个StandardClassLoader实例。具体的也可以在{catalina.home}/bin/bootstrap.jar包中的catalina.properites中进行配置。 3 StandardClassLoader加载{catalina.home}/lib下面的所有Tomcat用到的jar包。 4 一个Context容器,代表了一个app应用。Context–>WebappLoader–>WebClassLoader。并且Thread.contextClassLoader=WebClassLoader。应用程序中的jsp文件、class类、lib/*.jar包,都是WebClassLoader加载的。

当Jsp文件修改的时候,Tomcat更新步骤:

1 但访问1.jsp的时候,1.jsp的包装类JspServletWrapper会去比较1.jsp文件最新修改时间和上次的修改时间,以此判断1.jsp是否修改过。 2 1.jsp修改过的话,那么jspservletWrapper会清除相关引用,包括1.jsp编译后的servlet实例和加载这个servlet的JasperLoader实例。 3 重新创建一个JasperLoader实例,重新加载修改过后的1.jsp,重新生成一个Servlet实例。 4 返回修改后的1.jsp内容给用户。

当app下面的class文件修改的时候,Tomcat更新步骤:

1 Context容器会有专门线程监控app下面的类的修改情况。 2 如果发现有类被修改了。那么调用Context.reload()。清楚一系列相关的引用和资源。 3 然后创新创建一个WebClassLoader实例,重新加载app下面需要的class。

在一个有一定规模的应用中,如果文件修改多次,重启多次的话,java.lang.OutOfMemoryErrorPermGen space这个错误的的出现非常频繁。主要就是因为每次重启重新加载大量的class,超过了PermGen space设置的大小。两种情况可能导致PermGen space溢出。 一、GC(Garbage Collection)在主程序运行期对PermGen space没有进行清理(GC的不可控行), 二、重启之前WebClassLoader加载的class在别的地方还存在着引用。

class卸载、热替换和Tomcat的热部署的分析的更多相关文章

  1. 【转】class卸载、热替换和Tomcat的热部署的分析

    这篇文章主要是分析Tomcat中关于热部署和JSP更新替换的原理,在此之前先介绍class的热替换和class的卸载的原理.一 class的热替换ClassLoader中重要的方法 loadClass ...

  2. linux 热替换so文件

    http://www.zhaoch.top/操作系统/linux/热替换so文件.html 热替换so文件 www.zhaoch.top > 操作系统 > linux 发现nginx的动态 ...

  3. vue 无法热替换/热更新

    参考了小伙伴的解决办法: 1.https://blog.csdn.net/win7583362/article/details/65443291 虽然我并不是用对方的方法解决的. 依然还是建议大家打开 ...

  4. webpack 热替换

    一. 使用express.js搭建一个简易服务器demo地址,热替换的 先看包 // 清除重复的文件 "clean-webpack-plugin" // css加载器 " ...

  5. 透过现象看本质:Java类动态加载和热替换

    摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...

  6. Java_类的热替换

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/#ibm-pcon Java ClassLoader 技术剖析 在本文中,我们 ...

  7. 使用自己的ClassLoader实现热替换

    首先实现一个自己的ClassLoader,该ClassLoader重写findClass方法. 从classpath中加载类资源. 注意,不要重写loadClass方法.  因为在使用自定义的MyCl ...

  8. Idea maven tomcat 配置热更新 以及 maven jar依赖

    看了视频 实在忍不住上了idea的贼船 不过这玩意确实有点坑爹,因为用的人少,所以很多配置是有问题的 例如maven配置tomcat热更新 以及tomcat的maven配置 我这里放几张图作为备用 配 ...

  9. Java 类的热替换---转载

    构建基于 Java 的在线升级系统 Java ClassLoader 技术剖析 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于和构建在线升级系统相关的基础 ...

随机推荐

  1. 使用wget备份禅道

    禅道7.1,管理了公司所有项目.需要每月备份. 主机安装在一台windows上.为了方便,写个脚本自动调用禅道的备份功能,并把服务器上的备份文件下载到本地. @echo off setlocal re ...

  2. Json(2)-DataContractJsonSerializer

    public static void DataContractSerializeDemo()        {            User user = new User { UserID = 1 ...

  3. STM32调试大法 之 串口通讯

    开发过程经常需要查看某些特定参数.通常的方法可以使用paintf进行打印输出,观察具体的变量值.STM32内部集成有USART的串口功能,可以通过串口直接输出到电脑(上位机).使用非常方便,基本不需要 ...

  4. ASP.NET MVC +EasyUI 权限设计(二)环境搭建

    请注明转载地址:http://www.cnblogs.com/arhat 今天突然发现博客园出问题了,老魏使用了PC,手机,平板都访问博客园了,都是不能正常的访问,原因是不能加载CSS,也就是不能访问 ...

  5. ZOJ 2314 带上下界的可行流

    对于无源汇问题,方法有两种. 1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级 ...

  6. CodeForces 173B Chamber of Secrets 二分图+最短路

    题目链接: http://codeforces.com/problemset/problem/173/B 题意: 给你一个n*m的地图,现在有一束激光从左上角往左边射出,每遇到‘#’,你可以选择光线往 ...

  7. SVN--从本地检出项目至服务器报错--禁止访问

    错误描述: 原因:这是访问权限限制引起的. 查看/svn/test目录的权限--之前我修改过的 现在添加一个user就好了--这个添加的developer是我之前导入本地项目时已经验证过的,所以再导入 ...

  8. ComboTree使用

      1.参考资料 1.http://www.jeasyui.com/documentation/combotree.php 2.http://blog.csdn.net/woshichunchun/a ...

  9. 20160730noip模拟赛zld

    codeforces394E 如果没有在凸多边形内一点的限制,答案肯定是 如果不在凸多边形内,那么目标点肯定在凸多边形边上,我们枚举每条边,在每条边上求出距离平方和最小的点,在这些点中求出最小的 我们 ...

  10. 使用文本文件(.txt)进行数据存取的技巧总结(相当的经典)

    使用文本文件(.txt)进行数据存取的技巧总结(相当的经典) 使用文本文件(.txt)进行数据存取的技巧总结 由于本帖内容较多,部分转自他人的心得,因此,凡转贴的地方仅用“----转----”标注,原 ...