【转】JVM类装载机制的解析,热更新的探讨(二)
同样,一个Class对象必须知道自己的超类、超级接口。因此,Class对象会引用自己的超类和超级接口的Class对象。这种引用一定是实例引用。(实际上,超类、超级接口的引用也存储在常量池中,但为了区分依赖类的引用,将它特殊表述一下。)
因此,我暂且得到两条结论。
结论一:持有一个Class对象的引用,则任何该Class对象直接或间接依赖的所有类(如果被加载了),都不可能被卸载。同样,只要有一个类直接或间接依赖某个类,则该类不可能被卸载。
结论二:持有一个Class对象的引用,则该类的所有超类、超接口都不能被卸载。同样,如果任何一个类(或接口)存在一个没有被卸载的子类(或实现类、子接口),则该类(接口)不可能被卸载。
由此可见,对于一个软件而言,其所有class文件可以看做一个从包含main方法的根节点出发,在一张依赖图中搜索所有可达节点,所有可达节点构成的集合。而这个集合中的绝大部分类,要么全部保留在内存中,要么全部卸载。
对于一个模块而言,如果该模块之间的类彼此都存在依赖,则该模块必须整个地被卸载。因此,如果一个应用程序想要利用一个模块卸载另外一个模块。必要条件就是,执行卸载操作的模块必须零依赖被卸载的模块。
零依赖的含义就是,被依赖的模块是完全透明的,是不可见的。
根据上面的结论,卸载必须是以模块为单位。因此,所谓卸载一个强耦合的类是完全不可能的。因此,我可以放弃说“卸载类”,而应该说“卸载模块”。
那么,卸载一个模块的充分条件是什么呢?
回到前面的那张引用关系图,让我们来看看那些其他要素可能引用Class对象。

对于任何一个Java对象而言,它都一定是某个类的实例,因此,它能直接或间接的引用到该类的Class对象。这一推论的理由有三,其一,JVM在将对象进行向下转型、instanceof判定的时候,一定要知道对象的类型,倘若对象无法引用到类的Class对象,这个过程何以进行呢?其二,子类可重写父类的方法,运行时的多态令虚拟机能正确调用到对象方法(防止子类调用到父类被覆盖的方法),如果不知对象类型,何以实现?其三,Object类有一个native方法getClass()可以直接获取对象的类Class对象。
类加载器在加载了一个类之后,当第二次接受到该类的类名之后,加载器会直接返回该类的对象,而不是重复加载该类。虚拟机绝不允许同一个命名空间中的一个类被加载了两次,因此类加载器必须缓存所有它加载的类的Class对象,以供返回。
此外,ClassLoader也好,Class对象也好,这些本身能被变量所引用。如果某些可达的变量(局部变量、成员变量、静态变量)引用了它们,自然也会让整个模块变得可达而无法被卸载。
此外,某些特殊的类加载器永远是可达的,它们是Bootstrap、Extendsion、System。因此,我可以得出一条结论。
结论三:Java的标准类库一旦加载,永远不能卸载。
结论四:CLASS_PATH中的类(系统加载器加载的类),一旦加载,永远不能被卸载。
因此,一个模块中的所有类必须使用同一个ClassLoader实例加载。而且这个ClassLoader实例不能是Extendsion和System。这个ClassLoader实例的控制权必须掌握在操作卸载的模块那里。随时释放该实例的引用,使ClassLoader变得不可达。
此外,该模块任意类的实例都必须是不可达的,存在任何一个可达的该模块类的实例,模块都无法释放。
至此,我得到了卸载模块的充分条件:模块的全部类由一个可控的ClassLoader加载;释放该模块的定义类加载器引用;释放该模块所有类的实例引用;释放该模块的Class对象引用。
还有,模块的定义类加载器、类实例、Class对象,这些东西,只要没有引用掌握在其他模块那里,也没有掌握在栈内存中,就一定可以卸载模块。特别的,模块自己引用了这些东西,尤其是模块的静态变量引用了这些东西,那是完全不影响卸载的。
有一种观点认为,垃圾回收判断的根节点包括所有类的静态变量,这是错误的。实际上如果一个模块变得不可达了,它的所有的类的静态变量也会变得不可达,并会被回收释放。
转自:
http://taozeyu.com/software/2014/03/15/jvm-class-loader-2.html
【转】JVM类装载机制的解析,热更新的探讨(二)的更多相关文章
- 【转】JVM类装载机制的解析,热更新的探讨
引言 如有错误,请批评指正. Java是一种动态连接的语言.所谓动态连接,大概可以这么解释. 首先,Java可以大概想象成是编译解释执行的.对于一个*.java的文件,通过javac将会编译成一个*. ...
- 深入研究Java类装载机制
目录 1.为什么要研究java类装在机制? 2.了解类装载机制,对于我们在项目开发中有什么作用? 3.装载实现细节. 4.总结 一.为什么药研究Java类装载机制 java类加载机制,便于我们使用自定 ...
- JVM的类加载机制全面解析
什么是类加载机制 JVM把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被JVM直接使用的Java类型,这就是JVM的类加载机制. 如果你对Class文件的结 ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (二)
上次讲解了FairyGUI的最简单的热更新办法,并对其中一个Demo进行了修改并做成了热更新的方式. 这次我们来一个更加复杂一些的情况:Emoji. FairyGUI的 Example 04 - ...
- Unity热更新学习(二) —— ToLua c#与lua的相互调用
tolua 下载地址:http://www.ulua.org/index.html c#调用lua的方法,tolua的官方例子提供了很多种.我初步学了一种在做项目使用的方法.通过DoFile方法执行l ...
- Unity3D热更新全书-脚本(二) 两级分化
上篇明确了我们探讨的脚本是什么:是写在文本文件里面的代码,可以作为资源加载,取得字符串再执行. 可是为什么世界上会有那么多的脚本?而其使用方法完全看起来不一样呢?这是因为每种脚本都有自己的定位,在不同 ...
- Unity手游之路<十二>手游资源热更新策略探讨
http://blog.csdn.net/janeky/article/details/17666409 上一次我们学习了如何将资源进行打包.这次就可以用上场了,我们来探讨一下手游资源的增量更新策略. ...
- [unity3d]手游资源热更新策略探讨
原地址:http://blog.csdn.net/dingxiaowei2013/article/details/20079683 我们学习了如何将资源进行打包.这次就可以用上场了,我们来探讨一下手游 ...
- [转]Unity手游之路<十二>手游资源热更新策略探讨
最近梳理了下游戏流程.恩,本来想写下,但是,还是看前辈的吧 版权声明: https://blog.csdn.net/janeky/article/details/17666409 上一次我们学习了如何 ...
随机推荐
- iOS学习之字符串(NSString)的截取、匹配、分隔
截取 NSString *str1 = @"this is zero"; 1.从第三个字符开始,截取长度为2的字符串.........注:空格算作一个字符 NSString *st ...
- Ubuntu安装usb库
sudo pip install pyserial sudo pip install pyusb
- 全局启动函数start_kernel函数注解
asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start_ ...
- MySQL Network--域名与VIP
VIP与域名1.域名能在多个IDC切换,而VIP通常在特定网段内切换.2.VIP切换可以立即生效,而域名切换存在一定时间延迟. DNS解析顺序:1.查询本地域名映射配置(/etc/hosts)2.查查 ...
- centos7 安装 git服务器
服务器端配置 yum install -y git groupadd git useradd git -g git 2.创建authorized_keys cd /home/git mkdir .ss ...
- 【HICP Gauss】数据库 环境的搭建 -1
1.安装规则 1.主机名必须网络唯一 2.主机名必须两位数以上 可以中划线 不能下划线 3.固定IP地址 4.端口号 1888 新增账户 omm 用户组 dbgrp ,家目录 /home/ ...
- mysql:[Err] 1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
删除主键时,出错:[Err] 1075 - Incorrect table definition; there can be only one auto column and it must be d ...
- 渗透之路基础 -- XXE注入漏洞
XXE漏洞 XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件, ...
- selenium 全天课整理(二)
# encoding=utf-8 ''' selenium 全天 二 ''' #unittest例子 from selenium import webdriver import unittest,ti ...
- Java精通并发-从Thread与Runnable说起
java并发的学习从去年就已经中断了,之前只对于java并发的一些基础进行了一些巩固,对于这个硬技能不管是对于面试还是对于日常的实际开发来说都非常之重要,所以接下来给自己重新定一个新目标,准备重拾它一 ...