目录
一、Java内存分区
1.1 JVM栈和JVM堆
java中的每个线程都有自己专属的栈,这个栈是别的线程无法访问的,JVM栈是运行时的单位,JVM堆是存储的单位,JVM栈解决程序的运行问题(程序如何执行或者如何处理数据),JVM对解决数据存储问题。
★ 案例:
public void method1(){
Object obj = new Object();
}
obj相当于一个指针,放在JVM栈中,new Object()是对象实例,放在堆中。
更详细的解释如下:
1.1.1 Java栈
- Java栈用于存储正在调用中方法的所有局部变量(包括参数)
- 调用方法时,在栈中位该方法分配一块对应的栈帧,栈帧中包含所有的局部变量(包括参数),方法调用结束时,栈帧消失,局部变量一起消失
- 局部变量的生命周期,方法调用时存在,方法调用结束时消失
- 成员变量有默认值,局部变量没有默认值
/*
* 这个类使用来介绍Java堆栈的管理
* */
public class MemeryManage {
int a;
public void stack(int b) {
int c; // 局部变量
System.out.print("成员变量a:" + a + "
" +
"局部变量b:" + b + "
"
//编译错误,因为局部变量没有默认值
/* + "局部变量c:" + c*/ );
}
public static void main(String [] args) {
// 这一句在JVM中new了一个对象MemeryManage(),由于a是成员变量,所以在对象实例化的过程中就在堆中声明了a,
// 但是b和c是方法stack中的变量,需要调用时才会声明
// 定义了一个变量objA指向这个对象的地址
MemeryManage objA = new MemeryManage();
// 调用了stack()方法,在栈中声明了变量b和c
objA.stack(3);
// 方法执行完,栈帧消失,栈帧中的局部变量b和c消失
}
}
1.1.2 Java堆
new出来的变量存储在Java堆中
1.2 方法区
1.2.1 方法区介绍
方法区用于存放类的信息。Java运行时,首先会通过类装载载入类文件的字节码信息,经过解析后将其装入方法区。类的各种信息(包括方法)都在方法区中存储。
public class MemeryManage {
int a;
public void stack(int b) {
int c; // 局部变量
System.out.print("成员变量a:" + a + "
" +
"局部变量b:" + b + "
");
}
public static void main(String [] args) {
/*
* 调用堆栈之前,方法区中字节码文件先存在,实际上,他在我们程序开始运行前,java就会通过类装载载入类的字节码文件
* 对于MemeryManage来说,方法区中对应的字节码文件内容可以表示如下:
* MemeryManage.class{
* stack(),
* ...
* }
* 对象的字节码在方法区中只保留一份,无论多少次实例化MemeryManage这个对象,方法区中的字节码文件都不会变化
*/
MemeryManage objA = new MemeryManage();
objA.stack(3);
}
}
1.2.2 方法区识别方法调用对象的机制
在实例化对象时,传入this指针,来区分哪一个对象调用这个方法。
二、 JAVA内存管理机制
创建对象 他会给他做标记,如果还在引用+1 ,如果不用 类似归零,在eden 里面用完用 放到交换区 里面还在被引用再标识下在+1,这时如果一直积累不断累加,表明对象没有正常释放,可能是强引用,或者内存泄漏等。在创建对象之后,不适用这个对象时,可以用=null的操作,释放这个对象,但是因为JVM 有回收,所以开发人员养成习惯不这么写,但是碰到死循环 就会出现一直标识,那就是内存溢出或者泄漏
# 在一个java类中有如下代码
Cell c = new Cell();
c = null;
// c再赋值之后,又重新指向NULL,那么在JVM中,就认为new Cell()就已经没用了,是一个垃圾内存,在进行GC回收时,发现一块内存的引用次数为0,说明没有任何引用指向这个对象,就会将其回收。在Java中可以采用System.gc()的方式进行强制回收。
三、 JVM的GC机制
3.1 小GC机制
多个用户并发的过程中,JVM会将用户查询的数据先放在Eden区中,在Eden区放满的情况下,JVM会清掉没有未使用的对象(小gc),未被清掉的数据放在Survivor中(只有一块在用)FromSpace中。在FromSpace满了之后,清掉闲置的对象,将剩下的数据拷贝到ToSpace中,在ToSpace满了以后,清掉闲置的对象,拷贝至FromSpace中,这就是小GC的机制,下图表示堆中的Eden区可以正常回收。
3.2 大GC机制
当对象比较多的情况下,JVM会将Eden区、Survivor区中的还在使用的数据全部迁移到Old区中(小GC),当Old区满了以后,会强制做Full GC。这段时间系统的响应时间或多或少或比较慢。当获取的数据大于JVM的配置时,系统会频繁做Full GC。
3.3 JAVA虚拟机中的方法区、持久代、元数据区
JDK7之前,permanet genneration内存区域其实包含了两个部分:方法区和Interned String。在方法区中主要存储了class的一些信息,包括运行时的常量池、classloader的引用、字段数据、方法数据等等。Interned String内存区域是在JDK8的时候从JVM内存区域里面移除的
JDK8引入了一个新的native的内存区块,Metaspace,也就是元数据区