JVM 是 Java 程序员中高级开发的必备技能之一,也是未来长久发展的核心!!!~
JVM 是Java虚拟机。他它是实现Java代码,一处编写,处处运行的基础。也是Java二进制代码的运行环境
说明:内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
JVM 是一套规范,很多公司 都实现过JVM 我们常用的就是Open JDK、Oracle JDK,不同规范应用范围不同,同时受到的限制也不同!我们常用就是 OpenJDK
图1
图2
按顺序学习 由浅入深的学习 顺序是: JVM 内存结构 、 垃圾回收 、 Java Class编译优化 、 类加载器
顺序:
特点:
内存溢出:Out of Memory 是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。
下面是一个.class字节码信息
A : B C // D
0 : getstatic #20 // PrintStream out = System.out;
3 : astore_1 // --
4 : aload_1 // out.println(1);
5 : iconst_1 // --
6 : invokevirtual #26 // --
9 : aload_1 // out.println(2);
10: iconst_2 // --
11: invokevirtual #26 // --
14: aload_1 // out.println(3);
15: iconst_3 // --
16: invokevirtual #26 // --
19: aload_1 // out.println(4);
20: iconst_4 // --
21: invokevirtual #26 // --
24: aload_1 // out.println(5);
25: iconst_5 // --
26: invokevirtual #26 // --
29: return
说明 每一列是一串二进制字节码 由 A B C D 四部分组成
A 列:就是 程序计数器 记录的数字
栈帧包含的内容:
总结一句:栈帧内部自己的内存不用别人的,也不让别人用。就是线程安全的
递归调用导致栈帧过多,栈帧过大、或者第三方类库操作,都有可能造成栈内存溢出 java.lang.stackOverflowError ,推荐使用 -Xss256k 指定栈内存大小!
案例一:代码运行 CPU 占用过多 解决方法:Linux 环境下运行某些程序的时候,可能导致 CPU 的占用过高,这时需要定位占用 CPU 过高的线程
步骤:
用top命令得到进程(process ID)pid,再用ps命令得到进程pid中有问题的线程(thread ID)tid 最后用jstack 拿到tid 转为16进制 对比 nid
一些带有 native 的关键字修饰方法就是。需要 JAVA 去调用本地的C或者C++方法,因为 JAVA 有时候没法直接和操作系统底层交互,所以需要用到本地方法栈,服务于带 native 关键字的方法。
此图就是Object 的 clone方法 他是native修饰的 说明实现是有底层调用本地C 或者C++来实现的
特点
java.lang.OutofMemoryError :Java heap space. 堆内存溢出 可以使用 -Xmx8m 来指定堆内存大小。
代码
public class Jvm {
public static void main(String[] args) throws InterruptedException {
System.out.println("in 1");
Thread.sleep(30000);
byte[] bytes = new byte[1024 * 1024 * 10];
System.out.println("in 2");
Thread.sleep(30000);
bytes = null;
System.gc();
System.out.println("in 3");
Thread.sleep(1000000l);
}
}
1、查看当前系统中有哪些 java 进程
jps
当然知道我们Java项目的运行端口也可以 lsof -i:端口
2、查看堆内存占用情况 jmap – heap 进程id
jmap -heap 进程id
[root@iZuf6XXXXXXXvkjjn20Z ~]# lsof -i:18081
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 10140 root 166u IPv6 308674937 0t0 TCP *:18081 (LISTEN)
[root@iZuf6XXXXXXXvkjjn20Z ~]# jmap -heap 10140
Attaching to process ID 10140, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.121-b13
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 536870912 (512.0MB)
NewSize = 268435456 (256.0MB)
MaxNewSize = 268435456 (256.0MB)
OldSize = 268435456 (256.0MB)
NewRatio = 1
SurvivorRatio = 30
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 251658240 (240.0MB)
used = 207160352 (197.56350708007812MB)
free = 44497888 (42.436492919921875MB)
82.31812795003255% used
From Space:
capacity = 8388608 (8.0MB)
used = 2884576 (2.750946044921875MB)
free = 5504032 (5.249053955078125MB)
34.38682556152344% used
To Space:
capacity = 8388608 (8.0MB)
used = 0 (0.0MB)
free = 8388608 (8.0MB)
0.0% used
PS Old Generation
capacity = 268435456 (256.0MB)
used = 66860552 (63.76319122314453MB)
free = 201574904 (192.23680877685547MB)
24.907496571540833% used
40435 interned Strings occupying 4567600 bytes.
Eden区 就是我们每次new出来 在堆中使用的内存区域
指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
B站资源:https://www.bilibili.com/video/BV1yE411Z7AP
特殊说明: 解决问题的光鲜,藏着磕Bug的痛苦。 万物皆入轮回,谁也躲不掉! 以上文章,均是我实际操作,写出来的笔记资料,不会出现全文盗用别人文章!烦请各位,请勿直接盗用!