• Java内存管理01:JVM区域划分以及内存管理机制


    目录

    一、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栈

    1. Java栈用于存储正在调用中方法的所有局部变量(包括参数)
    2. 调用方法时,在栈中位该方法分配一块对应的栈帧,栈帧中包含所有的局部变量(包括参数),方法调用结束时,栈帧消失,局部变量一起消失
    3. 局部变量的生命周期,方法调用时存在,方法调用结束时消失
    4. 成员变量有默认值,局部变量没有默认值
    /*
     * 这个类使用来介绍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机制

    GC回收机制

    3.1 小GC机制

            多个用户并发的过程中,JVM会将用户查询的数据先放在Eden区中,在Eden区放满的情况下,JVM会清掉没有未使用的对象(小gc),未被清掉的数据放在Survivor中(只有一块在用)FromSpace中。在FromSpace满了之后,清掉闲置的对象,将剩下的数据拷贝到ToSpace中,在ToSpace满了以后,清掉闲置的对象,拷贝至FromSpace中,这就是小GC的机制,下图表示堆中的Eden区可以正常回收。

    小GC机制

    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,也就是元数据区

  • 相关阅读:
    回溯算法
    cannot import name 'np' in mxnet
    Linux后台运行任务 nohup &
    为Windows Terminal添加右键菜单
    Outlook设置QQ邮箱
    逻辑回归 logistic regression
    Python添加自定义目录到sys.path
    强化学习 策略梯度
    为Windows terminal preview添加右键菜单
    双系统使用Linux引导
  • 原文地址:https://www.cnblogs.com/gupan/p/9026094.html
Copyright © 2020-2023  润新知