jvm学习笔记
- 垃圾回收方法
- 标识算法:把没有引用的数据标记出来,然后进行清楚,缺点就是容易造成碎片化内存
- 引用计数算法:对每个对象保存一个整型的引用计数器属性,用于记录对象被引用的情况,只要对象的引用计数器的值为0,就可以进行回收
- 可达性分析算法:以根对象集合为起始点,按照从上到下的方式搜索被根对象集合所连接的目标对象是否可达
- 复制算法:把内存分成两半,把引用的数据复制到另外一半的内存中,然后清楚原来一般的内存,缺点就是造成内存浪费
- 标记整理算法:先把没有标记的数据清楚掉,然后整理被标记的数据。缺点就是效率低
- 标识算法:把没有引用的数据标记出来,然后进行清楚,缺点就是容易造成碎片化内存
- GC的演化 (随着内存的大小不断增长而演进)
- Serial
- parallel
- JVM生命周期
- 虚拟机的启动:是通过引导类bootstrap class loader创建个初始类来完成的
- 虚拟机的执行:
- 类的加载过程
- 加载
- 验证
- 准备
- 解析
- 初始化
- 类加载器的分类
- BootStrap Class Loader(启动类加载器:负责加载java类的核心内库)
- Ext Class Loader
- App Class Loader
- 双亲委派机制
- 优势:避免类的重复加载,保护程序的安全,防止核心API被随意篡改
- 沙箱安全机制:在项目中新建一个String类,写上main方法,包名是java.lang,启动项目的时候会报mian方法找不到,这样就叫沙箱安全机制,目的是保护核心API被随意篡改
- JVM中怎么标识两个Class对象是同一个类
- 类的完整类名必须一直,包括包名
- 加载这个类的Class Loader必须一样
- PC寄存器(程序计数器):存储下一条指令的地址。每隔线程都有它自己的程序计数器,是线程私有的
- 虚拟机栈(Stacks)
- 保存方法的局部变量
- 保存引用对象的地址
- 保存部分结果
- 设置栈的大小:-Xss
- 堆(Heap)
- 堆中(Eden)有一块缓冲区,是不被线程共享的,每个线程独有一份
- 初始内存是计算机物理内存的1/64
- 最大内存是计算机物理内存的1/4
- 新生代与老年代内存比列默认是1/2
- Eden空间和另外两个Survivor空间比列是8 :1:1
- 垃圾回收(GC)
- Mi0nor GC (发生在新生代)
- Major GC(发生在老年代)
- Full GC(对整个堆进行回收)
- 堆空间常用的参数
- Xms(初始堆的值)
- Xmx(最大堆的值)
- Xmn(设置新生代的大小)
- -XX:+PrintFlagsInitial(查看所有的参数的默认初始值)
- -XX:+PrintFlagsFinal(查看所有的参数的最终值)
- 逃逸分析:当一个对象在方法中被定义后,对象只在方法内部使用,则没有发生逃逸,否则就是发生了逃逸
- 字符串常量池
- 字符串常量池在堆中的原因:如果在元空间,只有Full GC才会清除,而Full GC只有当老年代跟元空间的内存都不足才会触发,很难去触发,所以放在了堆中,有利于快速清除没用的常量,提高效率
- 静态变量
- 方法区(Method Area)
- Class信息
- 域信息
- 方法信息
- JIT代码缓存
- 运行时常量池
- 常量池是Class文件的一部分,运行时常量池是对常量池的引用
- 对象创建的六个步骤
- 判断对象对应的类是否加载,链接,初始化
- 虚拟机遇到new的指令。先去元空间的常量池中定位一个类的引用,看看这个类是否被加载,解释,初始化,如果没有,那么在双亲委派的机制下,通过对应的类加载器去加载。如果没有找到对应的类,那么就会报ClassNotFoundException。
- 为对象分配内存
- 处理并发安全问题
- 初始化分配到空间
- 设置对象的对象头
- 执行init方法进行初始化
- 判断对象对应的类是否加载,链接,初始化
- 对象在内存中的布局
- 对象头
- 运行时元数据
- 哈希值
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 偏向线程id
- 偏向时间戳
- 类型指针:指向类元数据,确定该对象所属的类型
- 运行时元数据
- 实例数据
- 对齐填充
- 对象头
- 直接内存
- 在java堆外,是直接向系统申请的内存区域。来源于NIO
- 访问性能比堆高
- 可以用过MaxDirectMemorySize设置内存大小
- 如果不指定,默认与堆的最大值 -Xmx一样
- 执行引擎:执行jvm解析的字节码文件对应的指令
- JIT编译器:
- 字节码解释器:将字节码文件中的内容翻译为对应平台的本地机器指令执行
- -Xint: 完全采用解释器模式执行程序
- -Xcomp:完全采用即时编译器模式执行程序,如果即时编译器出现问题,解释器会介入执行
- -Xmixed:采用解释器+即时编译器的混合模式共同执行程序
- StringTable(字符串常量池)
- 字符串常量池中是不会存储相同内容的字符串,
- 是个固定大小的HashTable结果,通过-XX:StirngTableSize可以改变大小,1009是可以设置的最小值
- HashTbale短,性能差
- 常量跟常量相加,是在常量池中发生的
- 变量(引用类型)跟字符串相加,相当于在堆中new String()
- intern
- String s = new String("1")
- 这个是在堆中new了一个对象,在字符串常量池中存放了"1"
- s.intern()这个方法此时没啥用,在调用此方法前,字符串常量池中已经存了"1"
- String s2 = new String("1") + new String("1")
- 此时在字符串常量池中没有"11",原因是引用类型相加,相当于是new Stringbuild对象,然后用append()方法相加,此过程是在堆中进行的。
- s2.intern(),此时在字符串常量池中生产了"11"
- 如果字符串s在字符串常量池中存在对应字面量,则intern()方法返回该字面量的地址;如果不存在,则创建一个对应的字面量,并返回该字面量的地址
- String s = new String("1")
- String的垃圾回收
- -XX:+PrintStringTableStatistic -XX:+PrintGCDetails
- 内存泄露
- 只有对象不会在被程序用到了,但是GC又不能回收他们的情况,才叫内存泄露
- P170.待续。。