一, JVM 概述
JVM (JAVA 虚拟机), 定义了一套编译, 加载, 解释执行 JAVA 代码的规范,
基于这套规范市场上不同产品实现, 例如 Hotspot,JRockit,J9 等.
其简易内存体系结构如下:
二, 堆的内存划分:
Java 堆的内存划分如图所示, 分别为年轻代, Old Memory(老年代),Perm(永久代). 其中在 Jdk1.8 中, 永久代被移除, 使用 MetaSpace 代替.
1, 新生代:
(1)使用复制清除算法 (Copinng 算法), 原因是年轻代每次 GC 都要回收大部分对象. 新生代里面分成一份较大的 Eden 空间和两份较小的 Survivor 空间. 每次只使用 Eden 和其中一块 Survivor 空间, 然后垃圾回收的时候, 把存活对象放到未使用的 Survivor(划分出 from,to) 空间中, 清空 Eden 和刚才使用过的 Survivor 空间.
(2)分为 Eden,Survivor From,Survivor To, 比例默认为 8:1:1
(3)内存不足时发生 Minor GC
2, 老年代:
(1)采用标记 - 整理算法(mark-compact), 原因是老年代每次 GC 只会回收少部分对象.
3,Perm: 用来存储类的元数据, 也就是方法区.
(1)Perm 的废除: 在 jdk1.8 中, Perm 被替换成 MetaSpace,MetaSpace 存放在本地内存中. 原因是永久代进场内存不够用, 或者发生内存泄漏.
(2)MetaSpace(元空间): 元空间的本质和永久代类似, 都是对 JVM 规范中方法区的实现. 不过元空间与永久代之间最大的区别在于: 元空间并不在虚拟机中, 而是使用本地内存.
三, GC 垃圾回收:
常见的垃圾回收算法:
1,Mark-Sweep(标记 - 清除算法):
(1)思想: 标记清除算法分为两个阶段, 标记阶段和清除阶段. 标记阶段任务是标记出所有需要回收的对象, 清除阶段就是清除被标记对象的空间.
(2)优缺点: 实现简单, 容易产生内存碎片
2,Copying(复制清除算法):
(1)思想: 将可用内存划分为大小相等的两块, 每次只使用其中的一块. 当进行垃圾回收的时候了, 把其中存活对象全部复制到另外一块中, 然后把已使用的内存空间一次清空掉.
(2)优缺点: 不容易产生内存碎片; 可用内存空间少; 存活对象多的话, 效率低下.
3,Mark-Compact(标记 - 整理算法):
(1)思想: 先标记存活对象, 然后把存活对象向一边移动, 然后清理掉端边界以外的内存.
(2)优缺点: 不容易产生内存碎片; 内存利用率高; 存活对象多并且分散的时候, 移动次数多, 效率低下
4, 分代收集算法:(目前大部分 JVM 的垃圾收集器所采用的算法):
思想: 把堆分成新生代和老年代.(永久代指的是方法区)
(1) 因为新生代每次垃圾回收都要回收大部分对象, 所以新生代采用 Copying 算法. 新生代里面分成一份较大的 Eden 空间和两份较小的 Survivor 空间. 每次只使用 Eden 和其中一块 Survivor 空间, 然后垃圾回收的时候, 把存活对象放到未使用的 Survivor(划分出 from,to)空间中, 清空 Eden 和刚才使用过的 Survivor 空间.
(2) 由于老年代每次只回收少量的对象, 因此采用 mark-compact 算法.
(3) 在堆区外有一个永久代. 对永久代的回收主要是无效的类和常量.
几种不同的垃圾回收类型:
(1)Minor GC: 从年轻代 (包括 Eden,Survivor 区) 回收内存.
(2)Major GC: 清理整个老年代, 当 eden 区内存不足时触发.
(3)Full GC: 清理整个堆空间, 包括年轻代和老年代. 当老年代内存不足时触发.
- class classA{
- // 类加载时可以执行静态代码块, 但不一定会执行
- static {
- System.out.println(11);
- }
- }
- // 不会执行静态代码块
- loader.loadClass("cn.shizhe.ClassLoader.classA");
- // 会执行静态代码块
- Class.forName("cn.shizhe.ClassLoader.classA",true,loader);
- // 不会执行静态代码块
- Class.forName("cn.shizhe.ClassLoader.classA",false,loader);
- class class1{
- static int a = 100;
- static {
- System.out.println("class1.static");
- }
- }
- class class2 extends class1{
- static {
- System.out.println("class2.static");
- }
- }
- public class TestClassObject08 {
- public static void main(String[] args) {
- //class1 为主动加载, class2 为被动加载(不执行 static 初始化操作)
- System.out.println(class2.a);
- }
- }
来源: https://www.cnblogs.com/shi-zhe/p/11574438.html