`
臻是二哥
  • 浏览: 182662 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
Group-logo
Java技术分享
浏览量:0
社区版块
存档分类
最新评论

JVM-类型的生命周期

    博客分类:
  • JVM
阅读更多
类型的生命周期包括:装载,连接,初始化,卸载(和类装载器有关,不一定有)。
装载:将类的结构信息装载到内存中(这其中就包括很重要的角色--类的常量池,但是符号引用还没有解析),装载完毕之后会生成一个该类的Class对象。
连接:连接又包括验证,准备和解析。验证就是检验class文件语法等正确性。准备是为类变量分配内存并为他赋默认值。解析是将在装载阶段装载到内存中的常量池的符号引用解析为直接引用,这一步可以延后一直到类被首次主动使用的时候进行。关于首次主动使用,会在下文中说明。
初始化:初始化就是为类变量赋正确的值,在连接阶段,为类变量赋了默认的值,在这一步中,会将默认值修改为正确值。所谓正确值,就是程序员在程序中赋予变量的值。初始化过程会在一个类首次主动使用的时候进行。
一个类的初始化过程分为2个步骤:
1 如果该类存在父类,并且父类没有被初始化,则初始化父类。
2 如果该类存在<clinit>方法,执行此方法。

上面的第一条容易理解,我们来介绍第二条中的<clinit>方法。
<clinit>方法叫做类初始化方法,它专门负责执行“类变量初始化语句”和“静态初始化语句”。<clinit>方法在class文件生成时被创建。如果一个类没有类变量初始化语句,也没有静态初始化语句,那么该类就不存在<clinit>方法。
我们来看下面的例子:
public class Example {
	static int width=3;
	static int height=1+(int)(Math.random()*3.0);
	static int length;
	static {
		length=10+(int)(Math.random()*3.0);
	}
}

当这个类生成class文件时,会在class文件中生成<clinit>方法,<clinit>方法负责初始化类的height变量和length变量。为何没有width变量?weight变量会被编译器特殊处理为常量(这在生成class文件时就已经做好了)。也就是说在程序中的变量在class文件中不一定是变量,对于型如width这种初始化的变量会被优化为常量,存放在常量池中。当其他类引用Example.width时,会在其他类中直接存放一个3,而不是存放一个Example.width的引用。比如在类A中有语句int tmp=Example.width,那么在类A的常量池中会将tmp的值存储为3,而不是Example.width的引用。
另外,我们需要重点知道的是,jvm会保证<clinit>方法被同步的执行,这就是使用内部静态类实现的单例模式能保证线程安全的原因。
下面我们来说说什么叫主动使用?有6种行为被认为是主动使用:
1 创建类的实例
2 调用类中的静态方法
3 操作类中的非常量静态字段
4 调用java API中特定的反射方法
5 初始化一个类的子类
6 指定一个类作为启动初始化类
上面的6种行为其实很好理解,归根到底就是不初始化一个类程序执行不下去的时候,就要初始化一个类。下面给出一个例子:
class Parent{
	static int hoursOfSleep=(int)(Math.random()*3.0)+2;
	static {
		System.out.println("Parent was initialed!");
	}
}
class NewBaby extends Parent{
	static int hoursOfCry=3+(int)(Math.random()*3.0);
	static {
		System.out.println("NewBaby was initialed!");
	}
}
public class Example {
	public static void main(String [] args){
		int hours=NewBaby.hoursOfSleep;
		System.out.println(hours);
	}
	static {
		System.out.println("Example was initialed!");
	}
}


上面的代码输出结果为:
Example was initialed!
Parent was initialed!
2
我们来分析下值命令行中执行java Example之后的过程,首先装载Example的结构到内存中(包括常量池),接着验证,准备,连接。由于Example中没有类变量,不需要为类变量分配内存和赋值操作。接着初始化,初始化的时候会执行static块中的静态初始化语句,输出Example was initialed!。类Example装载完毕之后,就开始执行它的main方法啦!执行到main方法的第一句,需要使用NewBaby的hoursOfSleep,发现NewBaby类的hoursOfSleep变量指向Parent的hoursOfSleep变量。而要使用Parent的hoursOfSleep变量需要先将其初始化(只用初始化才会执行类中的类变量初始化语句和静态初始化语句),因此初始化Parent类,执行Parent类的<clinit>方法,返回hoursOfSleep的值。在执行Parent的<clinit>方法时自然会输出Parent was initialed!。接着程序继续执行主函数的println方法即可。我们可以看到:在程序执行过程中,没有必要初始化NewBaby类。
自此,我们介绍了一个java类装载,连接,初始化的过程,当然,当一个类型不在被使用的时候,我们可以选择将该类型从内存中卸载,但是常用的启动类装载器不支持卸载。
0
4
分享到:
评论

相关推荐

    Android静态变量的生命周期 简单介绍

    不过Android不太突出的进程概念,所以对静态变量的生命周期就会感觉模糊,这种模糊对于值类型是无所谓的,如果是静态的对象引用,则与内存回收、内存泄漏这些问题有关,有必要加深研究和理解。 一、静态变量在类被...

    免费超全面的Java基础类型,容器,并发,IO流,面向对象,Web编程等代码总结

    线程的创建方式与生命周期 线程核心机制,基础概念扩展 多线程并发访问,同步控制 线程间通信,等待/通知机制 锁锁机制,API详解 Fork/Join 框架机制详解 Executor线程池框架简介 面向对象 泛型机制与反射原理 ...

    Android中的内存泄漏

    长生命周期的对象持有了短生命周期的对象,从而导致短生命周期的对象不能被释放 垃圾回收机制 垃圾回收机制分为:引用计数法、可达性分析法 引用计数法(有循环引用的问题):Python、Object-C、Swift 用一个计数器...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    第7章 类型的生命周期 7.1 类型装载、连接与初始化 7.1.1 装载 7.1.2 验证 7.1.3 准备 7.1.4 解析 7.1.5 初始化 7.2 对象的生命周期 7.2.1 类实例化 7.2.2 垃圾收集和对象的终结 7.3 ...

    深入java.pdf

    这不是一本描述jvm是什么的文章,也不介绍jvm跨平台的特性,也不是讲述jvm安全特性的文章,更不是讲解jvm指令操作,数据运算的文章, 本文重点讲述 类型的生命周期.

    新版Android开发教程.rar

    ----------------------------------- Android 编程基础 1 封面----------------------------------- Android 编程基础 2 开放手机联盟 --Open --Open --Open --Open Handset Handset Handset Handset Alliance ...

    JVM—类加载过程学习

    其实,整个生命周期是7步,类从被加载到虚拟机内存中开始,到卸载出内存为止,分为:加载-&gt;验证-&gt;准备-&gt;解析-&gt;初始化-&gt;使用-&gt;卸载。 2 加载   加载分为三步: 1)通过全类名获取定义此类的二进制字节流; 2)将...

    解析Java类和对象的初始化过程

    类的初始化和对象初始化是JVM管理的类型生命周期中非常重要的两个环节,Google了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和JVM层次来分析的文章更是鲜有所见...

    Java后端面试问题整理.docx

    • 熟悉Java多线程并发中线程基本方法,线程池,线程生命周期,熟悉Java锁中常见锁分类(乐观/悲观锁、自旋锁、独/共享锁、可重入锁、公平/非公平锁、分段锁、偏向锁,轻/重量级锁)和基本的锁升级策略

    深入Java虚拟机(原书第2版)及书中源代码

    第7章 类型的生命周期 第8章 连接模型 第9章 垃圾收集 第10章 栈和局部变量操作 第11章 类型转换 第12章 整数运算 第13章 逻辑运算 第14章 浮点运算 第15章 对象和数组 第16章 控制流 第17章 异常 第18章 finally...

    MIDlet与Servlet通信的研究与设计

    J2ME 由两个主要的部件组成:特征和配置。前者是关于特定手持设备的Java API 集合的规格说明,包括运行特定设备中应用 ...出了诸如应用生命周期和特定设备联网之类的问题。使用MIDP 下的API 创建的各种应用即为MIDlet。

    学会这些java面试题让你吊打面试官

    1.Java中内存管理及各区域内存储数据的生命周期? 2.JVM堆内存的分代管理以及垃圾回收流程? 3.面向对象三大特征及详细理解? 4.重载与重写的区别? 5.接口和抽象类区别? 6.实例变量和静态变量的区别? 7.八大基本类型及...

    Android-Advance:安卓系统以及进阶教程

    注解的原理,利用注解可以干什么设计模式单例模式生产者消费者模式代理模式工厂模式建造者模式安卓Android基础活动的生命周期片段生命周期上下文类相关内容MVC,MVP,MVVM异同生命周期的应用RecyclerView的缓存原理...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【WEB】servlet 生命周期 35 【WEB】阐述JDBC操作数据库的步骤 36 【WEB】JSP内置对象 37 【WEB】JSP中的四种作用域 38 【WEB】转发(forward)和重定向(redirect)的区别 38 forward(转发): 38 redirect...

    [Java] 对象类型转换和运算符 instanceof 学习笔记 [#子类转父类 #父类转子类 #对象和引用的区别]

    [Java] 对象类型转换和运算符 instanceof 学习笔记 欢迎大家收看 把简单的问题变复杂系列 : ) ...正因为这个性质,导致引用变量的生命周期和其管理的对象相同。 内存区别:对象被实例化后要开辟内存空间,而引用对象

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    Android利用软引用和弱引用避免OOM的方法

     在Java中,虽然不需要程序员手动去管理对象的生命周期,但是如果希望某些对象具备一定的生命周期的话(比如内存不足时JVM就会自动回收某些对象从而避免OutOfMemory的错误)就需要用到软引用和弱引用了。...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

Global site tag (gtag.js) - Google Analytics