JAVA 虚拟机学习笔记

  本文是作者学习了《深入理解Java虚拟机_JVM高级特性与最佳实践 第2版》后的一些笔记和总结,希望对学习虚拟机的小伙伴有所帮助,如果想了解更多java虚拟机细节的小伙伴可以去阅读《深入理解Java虚拟机_JVM高级特性与最佳实践 第2版》;本文所讲JDK版本为OpenJDK 1.7,图片来自于《深入理解Java虚拟机_JVM高级特性与最佳实践 第2版》;

  • Java虚拟机运行时数据区域

                          

                                                                                      图 1-1

     如图1-1所示,java运行时数据区域主要包括方法区、虚拟机栈及本地方法栈、堆、程序计数器;

  1. 程序计数器:

程序计数器管理着很小的内存空间并且是线程私有的,里面存储着当前线程所执行的字节码的指令地址,字节码解释器就是通过改变这个计数器的值来获取下一条需要执行的字节码指令,如果线程执行的是一个Native方法则这个计数器的值为空

    2. 虚拟机栈:

虚拟机栈和程序计数器一样也是线程私有的生命周期和线程一样,虚拟机栈描述的是java方法执行的内存模型:每个方法在执行时都会创建一个栈帧用于存储方法的局部变量表、操作数栈、动态链接、方法出口信息等;方法的调用到执行完成的过程对应着虚拟机栈的栈帧入栈和出栈的过程;

   3.本地方法栈:

本地方法栈和虚拟机栈的功能大同小异,区别主要是虚拟机栈执行的是java方法,而本地方法栈执行的是虚拟机本地Native方法方法服务(可以包括其他的语言服务,如c/c++)

  4.Java堆:

Java堆是java虚拟机所管理内存最大的一块并且是线程共享的区域,它上面主要存放着java程序执行时所产生的实例对象,同时java堆也是GC比较活跃的区域,堆还可以细分为:新生代和老年代;再细分还可以分为:Eden空间、From Survivor、To Survivor空间等;

  5.Java方法区:

Java方法和Java堆一样是线程共享的区域,它上面主要存储着已被加载的类信息、静态变量、常量、即时编译器编译后的代码数据等信息;方法区也有可能发生GC,所以另一个别名也叫永久代;

  • Java 内存模型JMM(Java Merory Model)

前面已经介绍了Java虚拟机运行时数据区域及各个板块所储存的信息,现在来了解一下Java的内存模型:

其实Java虚拟机的内存模型和当前物理机的内存模型很相似,先看一看物理机的内存模型吧:

                                                               图 1-2

如图1-2所示描述了物理机的内存模型,每个处理器为了提高取数据和存数据的速度都会有一个高速缓存(就是我们电脑中处理器L1、L2缓存其读写速度接近处理器),因为涉及到存数据和读取数据都会进行IO操作,而IO操作又是一个相当耗时的操作,基于这种情况每个处理器都配备了相应的高速缓存,处理器所处理的数据就会先存入高速缓存,然后再同步回主内存中,读取同理;

通过上面的物理机内存模型我们可以对比Java的内存模型:

    

                                                             图 1-3

如图1-3所示为java的内存模型,工作内存就相当于高速缓存,在线程执行的时候工作内存中保存了被该线程使用的变量的主内存副本的拷贝,线程堆变量的读写操作等都在工作内存中进行,不同的线程之间的工作内存也是相互隔离的,不能访问,线程间变量的传递必须通过主内存来完成;

(注意:这里所说的主内存和工作内存与前面介绍的java内存区域中的堆、栈、方法区等不是同一个层次的内存划分,两者是没有关系的)

  • Java虚拟机类加载机制

Java类从被加载到虚拟机内存中开始到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用、卸载7个阶段,其中验证、准备、解析统称为连接,这7个阶段发生的顺序图;

   

                                                            图 1-4

如图1-4所示,加载、验证、准备、初始化、卸载这个5个顺序是固定的,解析可以在初始化阶段后执行(Java运行时绑定)

Java类加载的工程:

Java类加载的工程包括:加载、验证、准备、解析、初始化等5个阶段,下面详细说明5个阶段:

加载

加载阶段虚拟机需要完成下面3件事:

1、通过一个类的全限定名来获取定义此类的二进制字节流;

2、将这个二进制流所代表的静态存储结构转化为方法区的运行时数据结构;

3、在内存中生成一个java.lang.Class对象,作为方法区这个类的数据访问入口;

加载阶段完成后,二进制字节流就按照虚拟机所需的格式存入方法区中,然后再内存中实例化一个java.lang.Class对象(并没有明确规定是在java堆中,对于HotSpot机而言Class对象比较特殊,存在方法区里面),该对象作为程序访问方法区的数据的外部接口;

(注意:加载阶段和连接阶段的部分内容有可能交叉进行,如字节码文件格式的验证等)

验证

验证阶段目的是为了确保class文件字节流中包含的信息符合Java虚拟机规范要求,并不会危害虚拟机自身;验证阶段主要分为:

文件格式验证阶段、元数据验证、字节码验证、符号引用验证;

准备

准备阶段主要为静态变量分配内存并赋初始值阶段,这些变量所使用的内存都将在方法区中进行分配;

解析

解析阶段是虚拟机将常量池中的符号引用替换为直接引用的过程;解析主要针对类、接口、字段、类方法、接口方法、方法类型、方法句柄等;

初始化

在准备阶段变量已经赋过系统所给的初始值,而在初始化阶段则初始化我们主观定制的值,所以初始化阶段是执行类构造器<clinit>()方法的过程;

到这里已经介绍完了虚拟机的加载过程,如果有想知道更多细节的小伙伴请阅读《深入理解Java虚拟机_JVM高级特性与最佳实践 第2版》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值