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

目录
[TOC]

一、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 + "\n" +
        "局部变量b:" + b + "\n"
        //编译错误,因为局部变量没有默认值
        /* + "局部变量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 + "\n" +
        "局部变量b:" + b + "\n");
    }

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值