JVM 分析 (持续更新)
希望大家给点建议
JVM是什么
JVM是Java Virtual Machine(Java虚拟机)的缩写
Java虚拟机本质上就是一个程序。
JVM是处在操作系统之上,用来将java字节码,转化成能够支持运行的机器指令。
Java语言之所以兼容很多操作系统,最重要的一点就是,每个操作系统有对应的JVM,当系统安装配套的JVM后就可以运行java代码而且不需要关心java的兼容性。
JVM 运行时内存有那几快 (运行时区域)
创建类时运行图
当创建类时,类加载器将进行加载类的字节码文件然后存放在方法区中
而当创建类实例时,将在堆中申请一块内存空间(使用指针碰撞的形式存储)来存放类的实例数据并返回一个指针存放在栈中。然后通过栈中的指针来进行引用
类加载器
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构
类自带的三个类加载器
双亲委派机制
当加载类时,系统会从最顶层的Bootstrap ClassLoader 开始一级一级的往下找
这种先交给父类进行加载工作很符合它的名字
调用 *.getParent() 可以查找加载器 *.getParent().getParent() 可以查找父类的加载器。
GC垃圾回收
为什么要GC回收
如果没有用过C++的朋友可能不知道,在C++中创建类,当使用完类后必须要调用delete()函数进行释放内存,不然当内存空间不足时,系统将不能运行。
而由于JAVA底层实现是C/C++,所以它也需要释放不用的内存空间。但是由于它自身的GC垃圾回收机制使得我们不需要自己手动释放内存
怎样检测是否是垃圾
有两种算法可以实现这个功能
引用计数法
根搜索算法
引用计数法
每个类会有一个变量来记录当前类被引用的个数。
当创建一个类对象时,申请的这个堆内存里会存在一个变量值将会加1. 同时当引用不再引用这个类时,类变量值将减1
当类变量为0时,这个类也就没人引用,所以下载GC的时候会被清除
这种算法实现简单,判定效率也比较高。在python中就采用引用计数法进行内存管理。
但是这种算法不能解决对象的循环引用问题。
// 这时A B 各个引用值相加 都为 1
People A = new People();
People B = new People();
//这时引用值为2
A.instance = B;
B.instance = A;
//这时引用值会将为1
A = null;
B = null;
//这时在调用GC后由于A,B创建的类引用值为1所以不能被GC掉所以造成内存泄漏
System.gc();
所以在JAVA中 并没有采用这种方法
可达性分析算法
此算法的核心是通过一系列的 GC Roots 的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称之为”引用链”,当一个对象到GC Roots没有任何的引用链相连时(从GC Roots到这个对象不可达)时,证明此对象是不可用的。
对象Object 5 - 7 因为没有GC Roots 所有会被清除掉
这里我认为很好理解,首先GC线程(在Java中一直存在一个GC线程,所以当只有一个main函数线程的时候,其实Java正在运行的线程为两个) 开始进行遍历栈中的类引用指针,当指向的堆的内存块复制到to区中,然后遍历结束后会直接删除Eden,from 区的数据。这样实现GC的清除
在JAVA中,可以作为GC Roots
1.虚拟机栈中引用的对象(局部变量)
2.方法去中类静态属性引用的对象(static对象实例)
3.方法区中常量引用的对象(常量实例)
4.本地方法引用的对象
GC算法
https://blog.csdn.net/qq_35501660/article/details/83622479.
JVM调参
https://blog.csdn.net/hanghangaidoudou/article/details/86648470.
JVM面试题
https://blog.csdn.net/qq_41701956/article/details/100074023.
道行尚浅,希望大家积极留言