`

java程序的生命史梗概——笔记整理

 
阅读更多
从开始到生命周期结束,包括:编译、类加载、运行、GC几个步骤;
一、编译
1、词法、语法分析
词法分析是将源代码的字符流变成Token集合,而语法分析是根据Token序列抽象构造语法数的过程。
2、填充符号表
是由一组符号地址和符号信息构成的表格。后期由于开发需要,新开发了许多的数据结构和算法。大致有以下这些:无序链表中的顺序查找、有序数组中的二分查找、二叉查找树、平衡查找树(主要是红黑树)、散列表等。
3、语义分析
主要是对结构上正确的源程序进行上下文有关性质的检查。主要有以下几步:标注检查、数据和控制流分析、解语法糖。java中的语法糖主要有泛型、变长参数、自动拆箱/装箱、便利循环等,JVM在运行时不支持这些语法,便一阶段还原到简单的基础语法结构。
4、字节码生成
此阶段中,前面各个步骤中生成的信息转化成字节码写到磁盘中,还会进行少量代码添加和转换的工作。
二、类加载
  类加载的过程是在虚拟机内存的方法区进行,涉及到虚拟机内存。虚拟机内存呗划分为:程序计数器、栈、本地方法栈、堆、方法区、直接内存。
1、程序计数器:较小的内存空间,JVM概念模型中,字节码解释器工作就是改变计数器的指来选取下一条需要执行的字节码指令。
2、栈:
用于存储局部变量表、操作数栈、动态链接、方法出口等信息。其中局部变量表存放了编译时期产生的各种基本的数据类型、对象引用。
3、本地方法栈
本地方法栈为虚拟机使用的Native方法服务,甚至有的虚拟机会将两者合二为一。
4、堆
JVM管理内存中的最大一块。唯一的目的是存放实例对象。也是垃圾收集管理的主要区域,从内存回收的角度看:现在垃圾收集器都采用分代收集算法(后面会详细介绍),所以Java堆还可以进一步细分:新生代和老年代,而新生代进一步细分:Eden空间、From Survivor空间、To Survivor空间。为了效率考虑,堆还可能划分为多个线程私有的分配缓冲区(TLAB)。无论如何划分,都与存放内容无关,无论哪个区域,存放的依然是对象实例,它们存在的目的只是为了更好的回收和分配内存而已。
5、方法区
方法区与堆一样,都是线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。而运行时常量池是方法区的一部分,它主要用于存放编译期声明各种字面量和符号引用。
6、直接内存
直接内存并不是虚拟机运行时数据区的一部分,也是不Java规范中定义的内存区域,你可以简单理解为堆外内存,内存分配不受Java堆大小的限制但受整个内存大小的限制。
三、加载
1、在加载阶段,JVM需要完成三个步骤:首先通过类的全限定名来获取定义此类的二进制字节流,然后将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,最后在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据入口。在第一步获取二进制字节流中并没有明确指出从一个*.class文件中获取,规定的灵活性导致我们可以从ZIP(为JAR、EAR/WAR格式提供基础)包中获取,从网络获取(Applet),运行时计算生成(动态代理),其他文件产生(JSP文件生成的Class类),从数据库获取。
2、验证
了确保Class文件字节流中包含信息符合JVM的要求,因为Class文件的来源途径不一定中规中矩的从编译器产生,也有可能用十六进制编辑器直接编写Class文件。校验流程为文件格式校验、元数据验证、字节码验证
3、准备
正式为类变量分配内存并设置初始值的阶段,这些变量所使用的内存都在方法区进行分配。
4、解析
解析过程无非就是对类或接口、字段、接口方法进行解析
5、初始化
类初始化阶段是类加载过程的最后一步,在准备阶段,变量已经赋过一次初始值,而在这一步,则会根据程序猿定制的要求进行初始化类变量和其他资源。在这个阶段就是执行前面编译字节码生成流程提到的<clinit>()方法的过程。虚拟机也保证在多线程环境下这个方法被同时调用时被正确的加锁、同步,保证只有一个线程去执行这个方法而其他线程阻塞等待。
四、GC
JVM是如何判断程序药丸的呢?这地方其实采用了可达性分析算法,这个算法的基本思路是通过一系列的称为“GC Roots”的对象作为起始点,从这个节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时(用图论话说,就是从GC Roots到这个对象不可达),则证明此对象不可用,这时候就被判定为可回收的对象。当我们已经知道要回收的对象何时触发垃圾收集呢?安全点,安全点就是一些让程序暂定执行从而进行GC的位置,由此我们很容易知道GC停顿的时间是垃圾收集的核心。所有的垃圾收集算法以及衍生出来的垃圾收集器无不围绕着尽量减少GC停顿时间产生的,现在最新的G1垃圾收集器可以建立可预测的停顿时间模型,有计划的避免在整个Java堆中进行全区域的垃圾收集。
主要的垃圾收集算法及对应的垃圾收集器
1、标记-清除算法
最基础的收集算法,算法分为标记和清除两个阶段:首先标记处所有要回收的对象,在标记完成之后统一回收所有被标记的对象。它最大的不足是效率不高,还会产生大量不连续的内存碎片,这样导致的问题当程序运行过程分配较大对象时,即使堆中还有足够的内存,但是无法找到足够的连续内存只能不得不触发一次GC操作。这地方对应的垃圾收集器是CMS收集器。
2、复制算法
复制算法是为了解决效率问题而生的,它可以将可用内存容量划分为大小相等的两块,,每次只使用其中一块,当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样每次会对整个半区进行GC,并且不会产生内存碎片等问题。现在的商业虚拟机大多采用这种算法来回收新生代,另外划分内存比例也不是1:1,像HotSpot默认Eden(一块Eden区)和Survivor(两块Survivor区)的大小比例为8:1,每次使用Eden和其中一块Surviovr区,也就是新生代中可用内存空间是整个新生代的90%,当回收时,将Eden和其中一块Survivor中还存活的对象一次性复制到另一块Survivor中,最后清理掉Eden和刚才用到的Survivor空间,细心的读者在这地方也许会有发现,如果复制过程那块没使用的Survivor不够用怎么办呢?这时候需要依赖老年代进行分配担保。
3、标记-整理算法
算法是应用在老年代垃圾回收的算法,因为老年代不像复制算法那样回收频率高,另外它还会浪费空间。标记-整理过程与标记-清除差不多,无非后续步骤不是直接对可回收对象进行清除,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。这地方对应的垃圾收集器是Serial Old收集器、Parallel Old收集器。
4、分代收集算法
当前商业虚拟机都采用这种算法,它的思想就是我们前面提到的对堆内存区域进行分代,新生代和老年代,不同的区域采用不同垃圾收集算法。新生代用复制算法,老年代用标记-整理或标记-清除算法。
五、整理
举个例子回顾下整个流程,当我们new一个对象的时候,会经历什么呢?结合前面所说的,JVM遇到一个new指令时,首先去检查整个指令参数能否在方法区的常量池定位到一个类的符号引用,并且检查整个符号引用代表的类是否已被加载、解析和初始化过,如果没有,则必须先执行对应类加载过程。类加载检查通过后,接下来JVM将会为新生对象分配内存,这个过程是在堆中进行的,分配大小在类加载完成后就可以确定,如果堆内存是规整的,则采用指针移动对象大小相等距离即可,这种分配方式叫“指针碰撞”,如果是零散的,则JVM维护一个列表记录哪些内存可用,分配并更新列表记录,这种方式叫“空闲列表”,至于采用哪种方式,取决于我们前面提到的堆采用了哪种垃圾收集器决定的。划分完对象内存之后,虚拟机会进行必要的初始化操作,接下来需要对对象进行必要的设置,这些信息设置在对象头(类元数据信息、对象的哈希码、对象的GC分代年龄等等)里面,这些工作完成之后,一个新对象产生了,这地方其实还没结束,再下一步就是调用<init>()方法进行程序猿计划的对对象字段进行的赋值操作,最后设置栈中的引用指向这个堆中对象所在的内存地址(直接引用),这时候一个真正可用的对象已经产生了,至于后续对对象进行的各种操作及最后的死亡就是前面提到的字节码执行引擎啊GC。




分享到:
评论

相关推荐

    KJava深入浅出——Java在PDA上的程序设计

    《KJava深入浅出——Java在PDA上的程序设计》一书主要涵盖了Java技术在掌上设备(PDA)上的应用开发,旨在帮助开发者理解和掌握KJava编程的基础知识和实战技巧。KJava是Java Micro Edition (Java ME)的一个分支,...

    c++————————笔记

    根据提供的文档内容,我们可以归纳出一系列关于C++的重要知识点,这些知识点主要涵盖了C++的基础语法、数据类型、内存管理、程序结构以及高级特性如类、继承与多态等。下面将详细阐述这些知识点: ### 1. 引言 C++...

    浅谈Java线程的生命周期——北大青鸟佳音旗舰.docx

    总之,理解Java线程的生命周期和管理对于编写高效并发程序至关重要。开发者需要考虑线程的创建、启动、结束,以及如何有效地进行线程间的协作和调度,以确保程序的正确性和性能。在实际编程中,应遵循最佳实践,避免...

    手工完成java项目(一)——J2SE项目

    【标题】"手工完成java项目(一)——J2SE项目"揭示了这个压缩包文件是关于使用Java标准版(J2SE)进行项目开发的教程。在Java领域,J2SE代表Java 2 Platform, Standard Edition,它是Java平台的核心,主要用于桌面...

    Java Applet研究与应用——综合测评系统

    1. **Applet生命周期**:每个Java Applet都有其特定的生命周期,包括初始化(init()),启动(start()),暂停(stop())和销毁(destroy())四个阶段。理解这些阶段对于正确控制Applet的行为至关重要。 2. **图形...

    深入java虚拟机(三)——类的生命周期(下)类的初始化1

    【深入Java虚拟机(三)——类的生命周期(下)类的初始化1】 类的生命周期在Java中是一个关键的概念,它涵盖了从加载到卸载的整个过程。在类的生命周期中,初始化阶段是非常重要的,因为它涉及到类的静态变量的赋值...

    Java语言程序设计——基础篇

    根据提供的信息,“Java语言程序设计——基础篇”这本书主要针对初学者介绍了Java编程的基础知识。虽然部分内容并未给出具体章节或细节信息,但基于书名、描述及常见的Java基础教程内容,我们可以推测书中涵盖的主要...

    Java面试题——重整理版

    Java面试题涵盖了许多Java语言的核心概念,包括J2SE(Java 2 Standard Edition)的基础知识,JSP(Java Server Pages)、Servlet、JDBC(Java Database Connectivity)、JDO(Java Data Objects)、XML、EJB...

    JAVA多线程学习笔记整理(csdn)————程序.pdf

    Java多线程是Java编程中的核心概念,它允许并发执行多个任务,提高程序的执行效率。以下是关于Java多线程的详细知识点: 1. **创建线程** - **继承Thread类**:创建一个新的类,该类继承自Thread类,并重写run()...

    深入java虚拟机(二)——类的生命周期(上)类的加载和连接1

    【深入Java虚拟机(二)——类的生命周期(上)类的加载和连接】 Java虚拟机(JVM)是Java程序的核心,它负责解释和执行Java字节码。类的生命周期在JVM中是一个关键的概念,它涵盖了从类的加载到卸载的整个过程。...

    深入体验Java Web开发内幕——核心基础

    Java Web开发是构建互联网应用程序的重要领域,它涵盖了服务器端编程、网页交互以及数据库管理等多个方面。本主题将深入探讨Java Web开发的核心基础知识,帮助你全面理解这一技术的内在机制。 一、Java Web 开发...

    Java项目构建新型利器——Gradle

    随着现代软件开发的复杂性不断增加,构建自动化成为了一种必要,Java项目构建的新型利器——Gradle应运而生。Gradle是基于Java的下一代构建工具,它的出现改变了构建工具的格局,提供了更强的表现力和更好的可维护性...

    3.java学习第三章——变量.pdf

    ### Java学习第三章——变量 #### 一、字面量 在Java编程语言中,“数据”通常被称作“字面量”。字面量是指直接出现在程序中的常量值,例如数字、字符串或布尔值等。它可以直接表示该类型的值,无需通过变量间接...

    深入java虚拟机(一)——java虚拟机底层结构详解1

    Java虚拟机(JVM)是Java程序运行的核心组件,它为Java代码提供了跨平台的运行环境。JVM的底层结构主要包括几个关键部分:寄存器、栈和堆。 首先,JVM寄存器是虚拟机内部的一个概念,尽管实际硬件可能不包含与之...

    MLDN——Java Web 开发实战经典源码笔记(基础篇)|

    《MLDN——Java Web开发实战经典源码笔记(基础篇)》是一本专注于Java Web开发的实战教程,旨在帮助读者从零开始掌握Web应用的开发技术。这本书通过深入浅出的讲解和丰富的实例代码,全面介绍了Java Web开发的基础...

    轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发电子书1

    《轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发电子书1》是一本专注于Java EE企业级应用开发的书籍,主要涵盖了Struts 2、Spring和Hibernate这三个流行开源框架的整合应用。这本书对于Java...

    轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发电子书2

    《轻量级Java EE企业应用实战——Struts 2+Spring+Hibernate整合开发》是一本深入探讨Java EE企业级应用开发的书籍,尤其关注于轻量级框架的整合使用。Struts 2、Spring和Hibernate,简称SSH,是Java开发中最流行...

    Thinking in Java 自学笔记——第二章 一切皆对象

    ### Thinking in Java 自学笔记——第二章 一切皆对象 #### 重要概念解析 ##### 2.1 用引用操纵对象 在Java中,一切都被视为对象,这意味着无论是字符串、数字还是其他数据类型都可以被视为对象来进行操作。当...

Global site tag (gtag.js) - Google Analytics