Java虚拟机入门
一. JVM体系结构
1.1 JVM位置
JVM 是 JRE 的一部分,是 java 跨平台特性的基础
1.2 JVM体系图📛
二. 类加载器
2.1 类加载器
-
BootStrap ClassLoader 启动类 / 根加载器
-
Ext ClassLoader 扩展类加载器
-
App ClassLoader 系统类加载器
-
Custom ClassLoader 用户自定义加载器
2.2 双亲委派机制📛
原理:
- 类加载器收到类的加载请求 AppClassLoader
- 这个类向上委托父类加载器去加载,直到启动类加载器为止
- 启动类检查是否能加载当前类,能加载则加载,否则抛出异常通知子类加载
- 若找不到对应加载器则报错( Class Not Found 类没有被创建)
作用:
- 防止多次重复加载同一个类,保证数据安全
- 保证核心 .class 不被篡改,篡改的类不会被执行
2.3 沙箱安全机制
-
概念:java 安全模型的核心就是沙箱。沙箱机制就是将 Java 代码限定在虚拟机特定的运行范围中,并且严格限制代码对本地系统资源访问。
-
虚拟机把所有的代码加载到不同的系统域和应用域
- 系统域:负责与关键资源进行交互
- 应用域:通过系统域的部分代理来访问资源
-
沙箱组成
- 字节码校验器 - 核心类不需要通过校验
- 类装载器(双亲委派机制 \ 将代码归入保护域,确定权限)
三.运行时数据区
3.1 Native
概念:凡是带此关键字,说明 java 的作用范围达不到了,会调用底层C语言的库中的方法。
**作用:**扩展了 Java 的使用,融合不同的编程语言为 Java 所用。
- 本地方法栈 - 在内存中开辟的一块标记区域
3.2 方法区
方法区 :Method Area (方法区也是堆)
此区域属于共享区间,被所有线程共享。
存储元素:静态变量、常量、类信息(构造函数、接口)
3.3 PC寄存器(指针)
程序计数器:PCregister
每个线程都有一个程序计数器,是线程私有的,就是一个指针。
作用:在执行引擎要读取下一条指令时,用来存储指向下一条指令的地址
3.4 栈
先入后出表
3.5 堆 Heap📛
概述:一个 JVM 只有一个堆内存,堆内存大小是可调节的。
新生区中避免了被回收的,会重新进入新生区,达到15次(默认)进入养老区。
所以GC垃圾回收主要在新生区和养老区。
堆内存满了 > 报错OOM (OutOfMemoryError)
-
堆中的三个区域:
1.新生区(类诞生、成长和销毁的地方)
-
伊甸园区 : 对象在这里被new出来,满时触发轻GC,存活则进入幸存区
-
幸存0\1区:满时再次触发GC
2.养老区:该区满则触发重GC,若依然为满则报错OOM
3.永久区(元空间)
—存放JDK自带Class对象,不存在垃圾回收
—关闭虚拟机时才被释放
—接口 interface 将方法放置永久区
—逻辑上存在,实际物理空间不存在
-
-
堆例图
-
堆内存 默认:分配总内存是电脑的1/4;初始化内存1/64
-
OOM解决方案
(1)手动扩大内存
-Xms1024m -Xmx1024m -XX:+PrintGCDetails
-Xms
初始化内存大小-Xmx
最大内存大小(2)分析内存—调优
四.GC垃圾回收
4.1 内存分析工具:JProfiler
狂神 JVM:p9
优点:分析 dump 文件,快速定位内存泄漏点
使用:
1)在 Idea 上安装 JProfiler 插件
2)安装 JProfiler 客户端 ->注册
3)在Idea 中配置安装路径
4)输入命令:例 -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
5)分析:打开工具 > Biggest Object > 左侧 Thread Dump > 点击错误线程查看
4.2 两种GC
轻GC:普通GC
重GC:全局GC
4.3 GC 算法
-
引用计数法:每创建一个对象时,都为该对象分配一个计数器,计算每个对象的使用次数
-
复制算法:适用于对象存活率较低的场景,如幸存区
优点:没有空间碎片
缺点:会浪费一定的空间,如 幸存To区
-
标记清除:对活着的对象进行标记,对没有标记到的对象进行清除
优点:不会产生多余的空间
缺点:需要多次扫描 / 会产生空间碎片
-
标记压缩:再次扫描,向一端移动存活的对象,防止内存碎片产生
五.JMM
java内存模型 :Java Memory Model