浅聊JVM

浅聊JVM,第1张

浅聊JVM

1.什么是JVM?
JVM是java虚拟机,通过JVM,java可以实现平台无关性,也就是跨平台,java语言再不同的 *** 作系统运行时不需要重新编译,只需要再该平台上部署JVM即可,实现一次编译处处运行。
2.JVM结构
JVM主要包括:程序计数器,java堆,java虚拟机栈,本地方法栈(native stack),方法区。
首先我们知道编写的.java文件再编译后会生成.class字节码文件,然后由类加载器classLoader加载class文件。
2.1.聊聊类加载器classLoader
双亲委派机制
类加载器的作用就是加载class文件,将class文件加载进JVM中。JVM提供了三层类加载器:
Bootstrap classLoader:根加载器/rt.jar
ExtClassLoader:扩展类加载器jrelibext
AppClassLoader:加载应用程序的主函数类
classLoader在加载class文件时会经过以下步骤:
1.类加载器收到类加载请求
2.将请求向上委托给父类加载器,一直向上委托,直到根加载器也就是启动类加载器。
3.启动类加载器检查是否能加载当前类,能就加载,不能就抛出异常,通知子加载器加载,如下图

这就是双亲委派机制,使用双亲委派机制就是为了防止有人想替换系统级别的类,类加载器最先去根加载器加载,这样就直接防止危险代码的植入。
3.本地方法栈(native stack)
凡是带了native关键字的,说明Java的作用范围达不到了,会去调用底层的c语言库,进入本地方法栈。
本地方法的接口(JNI):扩展java的使用,融合不同的编程语言为java所用。
4.java虚拟机栈(FIFO)
栈是一种数据结构,遵循的是先进后出,后进先出的规则,经常会用来和队列比较,队列则是先进先出的规则。栈内存的生命周期和线程同步,线程结束栈也就over。所以我们创建线程后通过start方法执行线程,会在内存中自动创建栈,线程压栈出栈。所以栈内存中就不存在垃圾回收的问题,栈中主要存储的就是八大基本数据类型,实例方法和对象引用。栈的运行原理就是通过栈帧,也就是栈中的父帧和子帧相互调用。
5.堆
一个JVM只有一个堆,堆内存的大小是可以调节的
Java堆是被所有线程共享的一块区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存(随着技术的发展,已不绝对)
堆呢又分为这么几块区域:
伊甸园区也叫新生区(幸存0区 幸存1区)
养老区
永久存储区(再JDK8后叫元空间,这块区域只是逻辑存在,实际并不存在)
聊聊伊甸园区:
首先java堆的作用就是存放我们的对象实例,对象在创建后首先存储在伊甸园区,部分对象的新生和死亡都会在这,轻量级的GC(垃圾回收)会再这片区域进行垃圾回收(在伊甸园区的GC为复制算法),即不被引用的对象会被杀死,活下来的对象则会进入到幸存区,如对象A和对象B被创建在堆内存中也就是首先会在伊甸园区,在经历第一次垃圾回收之后,对象A就被杀死,对象B活下来则会进入幸存0区,在创建对象C在堆内存中,再次垃圾回收之后,对象C活下来,则对象A会和对象C一同进入到幸存1区,所以对象A是被复制到幸存1区的,对象0区此时就是空的,幸存1区和幸存0区是动态交换接收幸存对象,谁是空的谁就去接收幸存对象。这也就是GC的复制算法,JVM在进行垃圾回收的时候并不是对三个区域统一回收,大部分回收的就是新生区。
养老区则就是对象在经历15次垃圾回收之后还存活的就会进入养老区,这个15次是默认次数,可修改。
永久存储区存储类的元信息,静态变量和常量池等。
6.说说这个JVM调优
常说的JVM调优基本就是对堆内存进行调优。我们知道,如果栈内存满的话会报栈内存溢出,堆内存满的话会报OOM异常。对堆内存调优,1.我们可以通过扩大堆内存的空间
-Xms(数值)m -Xmx(数值)m -XX:+PrintGCDetails:查看GC清理的信息
2.分析内存看哪里出现了问题,我们可以使用JProfiler工具来查看内存的情况,这个工具的使用需要在idea中添加插件,使用以下代码先生成OOM的DUMP文件,使用JProfiler来查看分析内存问题
VM-Options: -Xms(数值)m -Xmx(数值)m -XX:+HeapDumpOnOutOfMemoryError:查看OOM DUMP
Xms(数值)m:设置初始化内存分配大小,默认六十四分之一
Xmx(数值)m:设置最大分配内存 默认四分之一
7.垃圾回收
首先垃圾回收的算法有标记清除法,标记整理,复制算法,引用计数法
引用计数法(废弃):给每个对象一个计数器,计数器本身也有消耗。使用过的对象计数,看其引用多少次。对象的引用次数为0,则清除该对象
复制算法:上文堆中伊甸园已说,复制算法的优缺点:
好处:没有内存碎片,都是整体迁移
坏处:浪费内存空间(一直空出一片幸存区(to区))假设对象100%存活,对象没有死亡的情况很浪费资源,所以复制算法最佳使用场景,对象存活度较低的时候。

标记清除算法:扫描所有对象,对活着的对象进行标记,清除没有标记的对象完成垃圾回收
缺点:两次扫描严重浪费时间,会产生内存碎片。
优点:不需要额外的空间

标记整理:防止内存碎片产生,对内存中的对象进行排序,产生连续空间。再次扫描,向一端移动存活的对象。多了一个移动成本

GC:分代收集算法
年轻使用复制算法,存活率低
老年代:标记清除+压缩算法

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/4748325.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-08
下一篇 2022-11-08

发表评论

登录后才能评论

评论列表(0条)

保存