JAVA虚拟机学习总结

1 篇文章 0 订阅

1.Java内存区域与内存溢出异常

在这里插入图片描述

  • 程序计数器–是一块较小的内存空间,当前线程所执行的字节码的行号指示器,每条线程都需要一个独立的Pc,如果线程执行的是java方法,记录的是正在执行的VM字节码指令的地址,native方法,则记录为空。是唯一一个没有规定OOM的区域
  • Java虚拟机栈–描述的是java方法执行的内存模型,每个方法在执行的同时都会建立一个栈帧,用于存储局部变量表(基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用,局部变量表所需内存空间在编译期间完成分配)、操作数栈、动态链接和方法出口等信息。每一个方法从调用到完毕的过程,都对应一个栈帧在VM中的入栈与出栈过程。
  • 本地方法栈–为虚拟机使用到的Native方法服务
  • Java堆–此内存区域的唯一目的是存放对象实例及数组,是垃圾收集器管理的主要区域,现代收集器都采用分代收集算法,java堆可再细分为新生代和老年代。
  • 方法区–用于存储已被VM加载的类信息、常量、静态变量、JIT(即时编译器)编译后的代码,此区域的内存回收目标主要是常量池的回收及对类型的卸载。
  • 运行时常量池(方法区的一部分)–用于存放编译器生成的各种字面量和符号引用及翻译出来的直接引用。具备动态性的特征,在运行期间可以将新的常量放入池中。
  • 直接内存–Direct Memory ,通过存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,避免了堆外内存和Java堆之间的来回数据拷贝,能显著提供性能。

2.虚拟机对象

  1. 对象的创建

指针碰撞:java堆中的内存是绝对规整的,使用Serial、ParNew等带压缩功能的收集器采用
空闲列表:JVM维护一个列表,记录哪些内存是可用的,分配时找到一个快足够大的内存空间划分给对象,并更新列表上的记录,使用CMS这种基于Mark-Sweep算法的收集器时采用。

  1. 对象的内存布局
  2. 对象的访问定位

使用句柄:最大好处是reference中存放的是稳定的句柄地址
直接指针:速度更快原因是减少了一次指针定位的时间开销,HotSpot使用。

3.垃圾收集器与内存分配策略

可作为GC ROOTS的对象包括:
虚拟机栈(栈帧中的本地变量表)中引用的对象

  1. 方法区中静态类型引用的对象
  2. 方法区中常量引用的对象。
  3. 本地方法栈中JNI(Native方法)引用的对象。

回收方法区(Hotspot中的永久代)

  1. 非常常量:没有任何对象引用的字面量
  2. 无用的类:(1)该类的所有实例都被回收,即java堆中没有任何该类的实例(2)加载该类的classloader已被回收(3)该类对应的Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

垃圾回收算法:
HotSpot的算法实现:

  • 根节点枚举–使用一组称为OopMap的数据结构来存放对象引用,在类加载完成的时候就把对象内什么偏移量上是什类型的数据计算出来,在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用,当GC扫描时就可以直接得知这些信息。
  • 安全点–是否具有让程序长时间执行的特征为标准进行选定,该标准的特点是指令序列复用,如方法调用、循环调转、异常调转等,具有这些功能的指令才会产生安全点。

让所有线程都到安全点停顿下来(1)抢先式中断(2)主动式中断-设置一个标志,各个线程执行时,会主动轮询这个标志,发现中断标志为真时,就自己中断挂起。轮询标志和安全点是重合的。

  • 安全区域–一段代码片段中,引用关系不会发生变化,在这个区域的任何地方发生GC都是安全的。

垃圾收集器
在这里插入图片描述

内存分配与回收策略:
**
### 4.性能监控与故障处理工具

5. 类加载的时机

在这里插入图片描述

类的生命周期
在这里插入图片描述
加载、验证、准备、初始化和卸载的顺序是确定的,必须按部就班的开始,解析阶段不一定。
初始化(主动引用):
(1)遇到new,getstatis,putstatis,innokestatis字节码指令时
(2)使用reflect包中的方法对类进行反射调用的时候
(3)初始化一个类的时候,父类没有初始化,先触发父类初始化
(4)虚拟机启动时,用户指定一个要执行的主类

6. 类加载的过程

(1)加载
a.通过类的全限定名获取定义此类的二进制字节流
b.将字节流代表的静态存储结构转化为放法区的运行时数据结构
c.在java堆中生成对应的Class对象,作为方法区的这些数据的访问入口
(2)验证
文件格式验证:字节流是否符合Class文件格式规范
元数据验证:对字节码描述的信息进行语义分析
字节码验证:进行数据流和控制流分析,对类的方法体进行校验分析
符号引用验证:确保解析动作能够正确执行
(3)准备
为类变量分配内存并为类变量赋初始值(通常是零值,如果被final修饰,则直接设置指定的值),这些内存都将在方法区分配。
(4)解析
将常量池中的符号引用替换为直接引用。主要针对类或接口、字段,类方法和接口方法这四类符号引用
(5)初始化
执行类中定义的JAVA代码(执行类构造器clinit()方法的过程)
clinit():编译器自动收集类中的所有类变量赋值动作和静态语句块合并产生的。

7. 类加载器

(1)类与类加载器
对于任意一个类,由加载它的类加载器和类本身确定其在JAVA虚拟机中的唯一性
(2)双亲委派模型
启动类加载器(Bootstrap ClassLoader):由C++语言实现,存放在<JAVA_HOME>\lib目录下,是虚拟机本身的一部分,无法被JAVA程序直接引用。
扩展类加载器(Extension ClassLoader):由sun.misc.Launcher $ExtClassLoader实现,加载<JAVA_HOME>\lib中,或被java.ext.dirs指定路径中的所有类库,开发者可直接使用
应用程序类加载器(Application ClassLoader:由sun.misc.Launcher $AppClassLoader,负载加载用户类路径(ClassPath)指定的类库,开发者可直接使用,没有自定义类加载器,是程序默认加载器。
类加载器之间关系:
在这里插入图片描述

实现原理:如果一个类加载器收到了类加载请求,不会立即处理,而是把这个请求委派给父类加载器处理(所有的加载请求都会被传到启动类加载器),只有父类加载器无法处理请求时,子加载器才会自己去加载。
作用:JAVA类随着它的类加载器具备了带有优先级的层级关系,类在各种加载器环境中都是同一个类,保证JAVA程序的稳定运行。(解决各个类加载器的基础类统一问题)
Classloader实现双亲委派源代码:
在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值