Class的生命周期
之前的《JVM类载入机制-ClassLoader》和《初探JVM-ClassLoader源代码》,仅仅是讨论了Class的载入部分,如今来纵观一下整个Class的生命周期。
Class的生命周期就是指一个class文件(字节码)从载入到卸载的全过程。
当一个类被装载、连接、初始化后,它的生命周期就開始了,当代表该类的Class对象不再被引用、即已经不可触及的时候,Class对象的生命周期结束。那么该类的方法区内的数据也会被卸载,从而结束该类的生命周期。
一个类的生命周期取决于它Class对象的生命周期,经历载入、连接、初始化、使用、和卸载五个阶段。
类的载入(Load Class)包括了下面三个步骤:
装载 Loading
查找Class的二进制文件(.class),把类的信息载入到JVM的方法区中。对其进行部分检验(类文件的魔数。文件长度,是否有父类等);在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。
载入方式有多种:A. 在classPath下找对应class文件;B. 从jar文件里读取;C. 从网络中获取;D. 实时生成。如设计模式中的动态代理模式;E. 从非class文件里获取,这些文件在jvm中执行之前也会被转换为可识别的字节码文件。
一般来说载入和连接是同步的,但有时候也会交叉进行,可是两者的開始和结束是顺序的。
链接 Linking
将相应的字节码文件读入到JVM中(当中解析步骤是能够选择的)
a) 验证
检查加载的class文件数据的合法性:字节码的格式,变量与方法是否反复、数据类型是否有效、继承与实现是否合法,接入属性是否正确(public ,private的问题),检查 final class 有没有被继承。检查静态变量的正确性等等。
b) 准备
给类的静态变量分配存储空间:赋default值(基本类型为0。引用为null)。静态常量(如final static int a = 100)。但不会对其进行初始化,不会运行不论什么 Java 代码(static块)。
c) 解析:
将符号引用转成直接引用。完毕内存结构的布局。
比如我们要调用Collections.toString()。java.util.Collections.toString()就是符号引用,而直接引用就是这种方法在方法区中的内存地址。
解析就是把类、接口、方法、成员变量的符号引用转换成内存地址,以供调用。
在连接阶段完毕后,再依据使用的情况(直接引用or被动引用)来决定是否类进行初始化。
初始化 Initializing
对静态变量赋assign值。运行静态代码块。 【类的初始化顺序能够參考我的《类的初始化&实例化顺序》】
在Java中类的引用分为直接引用和被动引用,仅仅有直接引用。会触发类的初始化:
a) new实例化对象;b) 使用类的(很量)静态变量 / 方法;c) 通过反射运行前三种情况。d) 子类被初始化;e) 作为程序入口。调用main(也是调用静态方法的一种)。
其它使用类的方式都叫被动引用,如:
a) 定义类数组。b) 引用类的静态常量;c) 引用父类的静态域,仅仅会触发父类的初始化,而不会触发子类的初始化。
从上面能看出。初始化的原则是,仅仅初始化要用到的。
在主动引用中,实例化(new/main)、使用静态域都是被用到了;而子类依赖了父类。所以也会触发初始化。在被动引用中,a中的类型仅仅是用于编译器的校验,而b中的静态常量是在链接中的准备阶段已经完毕了,所以两者都用不上去初始化。另外c中仅仅用到了父类的静态域,所以就不是必需触发子类。
public class LoaderLazy {
publicstatic String HELLO = "Hello";
static{
System.out.println("Init parent");
}
class SubLoaderLazy extends LoaderLazy{
static{
System.out.println("Init sub");
}
}
System.out.println(SubLoaderLazy.HELLO);
console:
Init parent
能看出上面仅仅初始化了父类。那假设我们把HELLO属性放在子类SubLoaderLazy中,子类也会被初始化。
console:
Init parent
Init sub
实例化 NewInstance
类的初始化完毕后。我们就能够创建对象实例了。
相比初始化仅仅运行类的静态域(静态变量/代码块)。类的实例化是运行类的实例域(非静态变量/代码块)和构造函数。而且在堆区创建一个类的实例对象。
(在实例化时,假设没有指定构造函数,JVM会自己主动构造一个无參构造函数。
)
类的实例化,一般在使用new创建对象。或者Class.newInstance()时运行。
【类的实例化顺序能够參考我的《类的初始化&实例化顺序》】
回收卸载 GC
Class作为JVM中的一个特殊对象,也会被GC回收卸载。
Class的卸载就是清空方法区中Class的信息和堆区中的java.lang.Class对象。这时Class的声明周期就结束了。
SUN的原话:“class or interface may be unloaded if andonly if its class loader is unreachable. Classesloaded by the BootstrapClassLoadermay not be unloaded”。
Class被回收要满足下面三个条件:
a) No Instance:该类全部的实例都已经被GC;
b) No ClassLoader:载入该类的ClassLoader实例已经被GC;
c) No Reference:该类的java.lang.Class对象没有被引用。(XXX.class, 静态变量/方法)
另外。有些Class是不会被回收的:
1、依据JVM和JLS的规范,由Bootstrap类载入器载入的Class在整个执行期间是不会被卸载的。
2、被Extension类载入器 和System类载入器载入的Class在执行期间不太可能被卸载,由于这些实例基本上在整个执行期间总能直接或者间接的訪问的到,其达到unreachable的可能性极小。
3、开发人员自己定义的类载入器载入的Class仅仅有在非常easy的上下文环境中才干被卸载,略微复杂点的应用场景中,非常难有符合上面3个条件的Class。
综合以上三点,一个已经载入的Class被卸载的几率非常小。并且卸载时间也是不可控的。并且Class占用的内存空间不大。一般不用考虑。
參考博客 http://blog.csdn.net/biaobiaoqi/article/details/6909141
Class的生命周期的更多相关文章
- react组件的生命周期
写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- C# MVC 5 - 生命周期(应用程序生命周期&请求生命周期)
本文是根据网上的文章总结的. 1.介绍 本文讨论ASP.Net MVC框架MVC的请求生命周期. MVC有两个生命周期,一为应用程序生命周期,二为请求生命周期. 2.应用程序生命周期 应用程序生命周期 ...
- UIViewController生命周期-完整版
一.UIViewController 的生命周期 下面带 (NSObject)的方法是NSObject提供的方法.其他的都是UIViewController 提供的方法. load (NSObje ...
- angular2系列教程(十一)路由嵌套、路由生命周期、matrix URL notation
今天我们要讲的是ng2的路由的第二部分,包括路由嵌套.路由生命周期等知识点. 例子 例子仍然是上节课的例子:
- Spring中Bean的作用域、生命周期
Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...
- Autofac - 生命周期
实例生命周期决定在同一个服务的每个请求的实例是如何共享的. 当请求一个服务的时候,Autofac会返回一个单例 (single instance作用域), 一个新的对象 (per lifetime作用 ...
- 【微信小程序开发•系列文章六】生命周期和路由
这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...
- Xamarin.Android活动的生命周期
一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没有丢失.可以看出app的“生命”是掌握在系统手上的, ...
- Mono产品生命周期
软件生命周期 同任何事物一样,一个软件产品或软件系统也要经历孕育.诞生.成长.成熟.衰亡等阶段,一般称为软件生命周期(软件生存周期) .软件生命周期模型是指人们为开发更好的软件而归纳总结的软件生命周期 ...
随机推荐
- 论js闭包的重要性
很久没写博客了,今天发现了一个很有意思的问题,写下来分享一下 话不多说,贴前端代码: <script type="text/javascript" src="js/ ...
- Java 之 StringTokenizer
class StringTokenizer Object to: break a string into tokens. Contructs StringTokenizer(String str) ...
- android高仿微信UI点击头像显示大图片效果
用过微信的朋友朋友都见过微信中点击对方头像显示会加载大图,先贴两张图片说明下: 这种UI效果对用户的体验不错,今天突然有了灵感,试着去实现,结果就出来了.. 下面说说我的思路: 1.点击图片时跳转到另 ...
- ACPI电源管理中的S0 S1 S2 S3 S4 S5
电源选项中S0,S1,S2,S3,S4,S5的含义以 ACPI 的规格来说吧!ACPI(Advanced Configuration and Power Interface),即高级配置与电源接口.这 ...
- 去除html页面中按钮在ios中的默认样式,去除select自带的小三角图标
btn{-webkit-appearance: none;} -webkit-appearance: none也能去掉select下拉列表后面自带的小三角
- python 下的数据结构与算法---3:python内建数据结构的方法及其时间复杂度
目录 一:python内部数据类型分类 二:各数据结构 一:python内部数据类型分类 这里有个很重要的东西要先提醒注意一下:原子性数据类型和非原子性数据类型的区别 Python内部数据从某种形式上 ...
- 读书笔记_Effective_C++_条款十五:在资源类管理类中提供对原始资源的访问
void f(int* a) { cout <<* a << endl; } int main() { shared_ptr<int> p(new int(3)); ...
- UVALive 5792 Diccionário Portuñol
字符串匹配问题 有n个a串个m个b串,讲a的前缀和b的后缀粘在一起有多少个不同的新串. 首先求不同的前缀和后缀肯定好求了,就用字典树分别存一下a个倒过来的b. 那个问题就是解决例如,abcd,和bcd ...
- linux int to string 方法
最近从windows 移植程序的时候发现to_string()函数在linux 中不能用,网上找了几种方法,觉得使用stringstream对象来实现类型转化比较好一点. 你只需在你工程中加入下面的t ...
- sql_autoload_register() 函数 和__autoload() 的区别
1:__autoload($class) 因为是一个函数,所以只能定义一次,使用多个会冲突报错;而 sql_autoload_register('function') 可定义多个,它有效地创建一个队列 ...