JVM整理

1、JVM 的位置

存在操作系统(Windows、Linux、,Mac)上,JRE包含JVM,操作系统存在于硬件系统(Inter、Spac)上,Java程序在JVM运行

2、JVM 的体系结构

Java à Class File à 类加载器(Class Loader)à运行时数据区(Runtime Data Area)也就是虚拟机:

方法区(Method Area):

Java栈(Stack):

本地方法区(Native Method Stack):

堆(Heap:JVM中99%调优的地方):

程序计数器:

à另外,执行引擎,本地方法接口(本地方法库)

3、类加载器(Class Loader)

作用:加载Class文件,类是模板,对象是具体的实例

应用程序加载器 à 扩展类加载器 à 启动类(根)加载器 à 虚拟机自带的加载器

4、双亲委派机制:安全:APP à EXC à BOOT (最终执行)

类加载器收到类的请求,将这个请求委托给父类加载器去完成,一直向上委托,直到启动类加载器,启动加载器检查是否可以加载当前类,能加载就结束,否则抛出异常,通知子加载器进行加载,重复检查操作(class not found)

5、沙箱安全机制

基本组件:字节码校验器与类装载器

类装载器:防止恶意代码去干涉善意的代码,保护被信任类的边界,将代码归入保护域,确认代码可以执行哪些操作,包括存储控制器和安全管理器

6、Native

Native:凡是带native关键字的,说明java的作用范围达不到了,回去调用底层C语言的库,会进去本地方法栈调用本地方法本地接口 JNI(扩展java的使用,融合不同的的编程语言为java所用),它在内存区域中专门开辟了一块标记区域:Navtive Method Stac,登记native方法,在最终执行的时候加载本地方法库中的方法通过JNI

应用区域:程序驱动打印机,管理系统

7、PC 寄存器(程序计数器)与方法区与三种JVM(Sun公司、)

每个线程都有一个程序计数器,线程私有的,就是一个指针,内存空间极小,忽略不计

方法区: 静态变量、常量。类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆的内存中,和方法区无关

JVM :Sun公司、BEA、IBM

8、栈(数据结构):先进后出,后进先出(原型:桶)

队列:先进先出(FIFO:first input first ouput)

栈内存:主管程序的运行,生命周期和线程同步,线程技术,栈内存也就释放,对于栈来说,不存在垃圾回收问题,一旦线程结束,栈就over了

栈内存:八大基本类型+对象引用+实例的方法

栈运行原理:栈帧,程序正在执行的方法,一定在栈的最顶部

栈溢出异常:

java.lang.StackOverflowError (-Xms8m -Xmx8m -XX:+PrintGCDetails)

栈+堆+方法区关系:栈中放引用(new Student),堆中放对象具体的实例,实例中的常量去常量池中获取,常量池在方法区中

9、堆与堆内存调优

Heap:一个JVM只有一个堆内存,堆内存的大小是可以调节的

存放内容:类,方法,常量,变量~,保存我们所有引用类型的真是对象

三个区域:GC 垃圾回收主要在伊甸园区与养老区

新生区(Young/New):类诞生和死亡的地方,伊甸园区(new出来的地方)、幸存区(0,1),轻量级GC

养老区(Old):重GC(Full GC)

永久区(Perm):JDK8之后,改名叫元空间,JDK1.6之前为永久代,常量池在方法区,JDK1.8之后,无永久代,常量池在元空间(逻辑上存在,物理上不存在)

内存满了异常:OOM,内存不足(java.lang.OutOfMemoryError)

OOM 排查错误:( 默认情况下,分配内存是电脑内存的:1/4,而初始内存为:1/64**)**

第一步:尝试扩大堆内存看结果

调整分配内存,并打印GC内存细节:-Xms1024m -Xmx1024m -XX:+PrintGCDetails

第二步:分析内存,专业工具(内存快照分析工具:JProfilter/MAT)排查问题具体地方

分析工具:分析Dump文件,快速定位内存泄漏,获取堆中数据,获取大的对象

VM 参数导出Dump文件:-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

分析当前对象集与想成存储,定位错误的位置

参数: -Xms初始化内存,-Xmx最大分配内存,-XX:+PrintGCDetails打印垃圾回收信息,-XX:+HeapDumpOnOutOfMemoryError文件Dump(oom)

10、GC (轻GC-普通,重GC-全局)

常用算法:

引用计数法、

复制算法 (幸存区0与1,设置GC次数进入老年区),好处没有内存碎片,坏处但浪费内存空间,多了一半空间永远为to

标记清除算法 (一次扫描标记活着的对象,一次扫描清除没有标记的对象),好处不需要额外的空间,坏处是两次扫描,浪费时间,产生内存碎片

标记压缩算法 :防止内存碎片产生,(三次扫描)再次扫描,移动一段存活的对象

总结:

内存效率:复制算法>标记清除算法>标记压缩算法

内存整齐度:复制算法=标记压缩算法>标记清除算法

内存利用率:标记压缩算法>标记清除算法>复制算法

年轻代:存活率低,用复制算法

老年代:区域大,存活率,标记清除(内存碎片不是太多)+标记压缩混合 实现

相关推荐
echoyu.4 小时前
java源代码、字节码、jvm、jit、aot的关系
java·开发语言·jvm·八股
代码栈上的思考18 小时前
JVM中内存管理的策略
java·jvm
thginWalker21 小时前
深入浅出 Java 虚拟机之进阶部分
jvm
沐浴露z1 天前
【JVM】详解 线程与协程
java·jvm
thginWalker1 天前
深入浅出 Java 虚拟机之实战部分
jvm
程序员卷卷狗2 天前
JVM 调优实战:从线上问题复盘到精细化内存治理
java·开发语言·jvm
Sincerelyplz3 天前
【JDK新特性】分代ZGC到底做了哪些优化?
java·jvm·后端
初学小白...4 天前
线程同步机制及三大不安全案例
java·开发语言·jvm
凤山老林4 天前
还在用JDK8?JDK8升级JDK11:一次价值千万的升级指南
java·开发语言·jvm·spring boot·后端·jdk