本文主要是针对JVM的一些小知识点进行梳理,如有什么地方有误或者不明白,欢迎指正讨论。
持续更新中… …
1. 内存回收
1.1. 线程栈帧中局部变量表的内存回收
- 复用含义:线程的局部变量表是可以被JVM给复用的,首先要说的是变量槽,即slot,也就是局部变量表中的各个存放数据类型的位置。所谓复用,即局部变量表中的一个变量在确认不会被使用后,其他变量可以存放在这个位置上,以此来节省空间。
- 内存泄露情况:当变量不再被任何方式引用的时候,如跳出该变量的作用域,与此同时,也没有新的变量对其复用,则局部变量表仍然保持着对它的引用,而局部变量表作为GC Roots的一部分,使得这一部分变量空间不能被JVM回收,如果后续要运行很长时间才会对这部分进行复用或者跳出线程,那么会使得这部分内存一直被占用着。
- 避免方式:就如复用的含义一样,可以在变量不再使用后,对局部变量表进行一些操作,如例子中的
willbegc1()
,使得局部变量表更新,但是这样挺不科学的,因为看起来会和代码逻辑没啥关系。另一种方法就是在一个变量不再使用的时候给他赋值为null。 - 例子
public class jvmTestMain {
public static void main(String []args){
System.out.println("Start wontbegc():");
wontbegc();
System.out.println("Start willbegc1():");
willbegc1();
System.out.println("Start willbegc2():");
willbegc2();
}
//不会被回收的placeholder
public static void wontbegc(){
{
byte[] placeholder=new byte[64*1024*1024];
}
System.gc();
}
//会被回收的placeholder
public static void willbegc1(){
{
byte[] placeholder=new byte[64*1024*1024];
}
int a=0;
System.gc();
}
//会被回收的placeholder
public static void willbegc2(){
{
byte[] placeholder=new byte[64*1024*1024];
placeholder=null;
}
System.gc();
}
}
- 实验结果: