JVM和GC
1、jvm基础知识
1.1、什么是jvm
java虚拟机(java virtural machine),是虚拟机的一种,虚拟机指以软件的方式模拟具有完整系统功能,运行在一个完全隔离环境中的完整计算机系统,是物理机的软件实现。常用的虚拟机有:VM Ware、Visual Box、Java Virtual Machine
jvm 和 java 无关
1.1.1、常见的jvm
1.2、虚拟机的启动
jvm的启动是通过类加载器(bootstrap class loader)创建一个初始类来完成的,这个类是由虚拟机的具体实现指令来指定的。
1.3、虚拟机的退出
(1)某线程调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且java安全管理器也允许这次exit或者halt操作;
(2)程序正常执行结束;
(3)程序在执行过程中遇到异常或者错误;
(4)操作系统出现错误;
1.4、jvm内存结构
1.4.1、JDK、JRE、JVM
1.5、什么是垃圾?如何定位垃圾?
1、申请内存new
2、释放内存 程序自动回收
好处:
(1)不会忘记回收
(2)不会多次回收
3、垃圾:没有任何引用指向的一个对象或者多个对象(循环引用)
4、定位垃圾:
(1)reference count (引用计数):在对象上记录一个数字,有多少引用指向;但是无法定位多个对象循环引用的垃圾,会产生内存泄漏;
(2)root searching(根可达算法)
A、根对象:线程栈变量、静态变量、常量池、JIN指针引用到的变量
5、常见的垃圾回收算法
(1)mark-sweep(标记清除):跟可达对象进行标记,非跟可达对象进行清除;
缺点:垃圾清除后会产生内存碎片,位置不连续;
(2)copying(拷贝):准备两份内存,将A内存中的存活对象copy到B内存中,而然后将A内存中的对象全部清除;
缺点:占用内存,浪费空间
(3)mark-conpact(标记压缩):将跟可达对象进行标记,移动所有的可达对象到堆内存的同一个区域,从而将所有非可达对象释放的内存放到一起,通过这样的方式来达到减少内存碎片的目的。
缺点:和上方两个算法比较,效率低
1.6、jvm内存分代模型–用于分代垃圾回收算法
1、部分垃圾回收器使用的模型
2、新生代+老年代+永久代(1.7)/元数据区(1.8 metaspace)
1)永久代 元数据区 存放 Class对象、常量池
2)永久代必须指定大小,可能会出现永久代内存溢出;元数据区开可以设置,也可以不设置,无上限,受限于物理内存
3)字符串常量 1.7-永久代 1.8-堆
1.7、堆内存逻辑分区
新生代:老年代=1:2
新生代=eden:survivor:survivor=8:1:1
新时代有2个survivor,为什么?为了方便垃圾回收,使用copying算法进行垃圾回收
1)YGC、回收之后,多数对象被回收,少数存活对象进入s0
2)再次YGC后,存活的对象Eden+s0 ->s1
3)再次YGC后,存活对象EDen+s1->s0
4)年龄足够进入老年代
5)s区装不下->老年代
老年代
1)顽固分子
2)老年代满了FGC Full GC(尽量减少FGC)
GC Tuning
1)MinorGC==YGC
2)MigorGC==FGC
3)尽量减少FGC
1.8垃圾回收器
2、类加载器
类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
参考文档:https://blog.csdn.net/q982151756/article/details/81540903
2.1 双亲委派模型
双亲委派模型的工作过程如下:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围内没找到这个类)时,自加载器才会尝试自己加载。
双亲委派模型是为了保证 Java 核心库的类型安全。所有 Java 应用都至少需要引用 java.lang.Object类,也就是说在运行的时候,java.lang.Object这个类需要被加载到 Java 虚拟机中。
参考文档:https://blog.csdn.net/q982151756/article/details/81540903