Java内存相关知识整理

来源:互联网 发布:洛阳达内大数据培训 编辑:程序博客网 时间:2024/05/22 05:13

最近心情不大好,没心思继续深挖SpringMVC,所以那个坑今天暂时不填,找点Java内存相关的内容随便看看写写,只是写写自己的理解,有不正确或不准确的地方请见谅.
一直以来,对于Java,或者说JVM的内存认识,都是零零碎碎的,这次正好借这个机会给自己整理一下.

Java内存区域

在理解JMM前,我们需要先了解一下Java内存区域的划分:

  • 方法区(Method Area):
    方法区又叫静态区,静态区是线程共享的,从JMM角度讲属于主内存,主要用于存储静态变量,常量等数据.(方法区的实现即堆模型中的永久代,详情参照JVM堆模型部分)
  • JVM堆(Java Heap):
    堆是线程共享的,从JMM的角度也存在于主内存,主要存储程序创建的对象实例及引用类型数据的实例,是JVM内存中占用最大的一部分.值得注意的是,这里同时是Java垃圾收集器主要关注的位置,所以也被称作GC堆.
  • 程序计数器(Program Counter Register):
    Java程序是需要编译成字节码文件(class文件)在JVM上执行,在执行的过程中,经常会遇到分支、循环、跳转、异常处理、线程恢复等导致字节码文件不能顺次执行的处理,程序计数器作为字节码文件的行号计数器,可以用来记录字节码文件的位置,从而为非顺次执行字节码文件提供跳转的指向,程序计数器只占用很小的一块内存.
  • JVM栈(java Virtual Machine Stacks):
    JVM栈是线程私有内存,主要存储线程的变量地址及值类型数据,每新创建一个线程,JVM都会在内存新分配一个JVM栈提供给线程.
    -本地方法栈(Native Method Stacks):
    本地方法栈属于线程私有内存,这部分涉及到Java的Native方法,以我目前的经验讲,除了在查看jdk源码时碰到过之外并没有其他涉及,所以这部分目前没有很详细的说明.

JMM(Java内存模型)

Java内存模型规范了JVM在计算机内存中的工作方式,JVM内运行的实体是线程,JVM在每次创建线程时都会为线程分配一个工作内存用于存储线程的私有数据,这个私有数据指的是程序计数器、JVM栈以及本地方法栈.
由于对象实例及引用类型的数据实际是存储在主内存(JVM堆)中,所以线程操作这一类变量的过程需要先从JVM堆将变量拷贝至JVM栈,在栈上对变量进行操作后再写回.

JVM堆模型

前文提到过,Java垃圾收集器主要关注的位置是JVM堆,Java从J2SE1.2起即使用了分代回收算法,下图为分代模型,也叫堆模型.
这里写图片描述

  • 年轻代(Young Generation)
    年轻代包含3个部分,1个伊甸园(Eden Space)和2个幸存者区(Survivor Space),伊甸园是对象最初生成的位置,所有新创建的对象都将在这里分配内存,当伊甸园的内存不足时,会进行一次Minor GC(详见文后注),将GC后仍存活的对象通过复制算法(Coping Collector)拷贝到Survivor Space0,伊甸园重置为空闲区,当伊甸园再次内存不足,将再次进行Minor GC,将伊甸园与Survivor Space0中仍存活的对象拷贝到Survivor Space1,重置伊甸园与Survivor Space0为空闲区,依此循环.
  • 年老代(Old Generation)
    当幸存者区内存不足时,将会执行一次Minor GC,此时幸存者区中根据来源区分出两种对象,一种是从伊甸园拷贝过来的,这种对象将通过复制算法拷贝到另外的空闲的幸存者区,另一种是从其他幸存者区拷贝过来的,这一类对象将会通过复制算法被拷贝到年老区.当年老区内存不足时,将会进行Full GC(详见文后注).
  • 永久代(Permanent Generation)
    永久代即我们常说的”常量池”,是JMM规范中方法区的具体实现,用于存放静态对象.
    需要注意的是,JDK 8已经移除了永久代,并引入了”元空间”的概念,将JDK 6以前需要存储在永久代的数据移动元空间来存储,而JDK 7虽然在Hotspot中仍存在永久代,但相关的数据已经移动到JVM Heap或Native Heap中存储了.
  • 元空间(Metaspace)
    元空间作为替代永久代的存在,其本质同样是JMM规范中方法区的实现,不同的是,元空间存在于虚拟机之外,使用的是本地内存,所以元空间只受本地内存的限制.

注:

  • Minor GC:从年轻代回收内存
  • Major GC:从年老代回收内存
  • Full GC:从整个堆空间回收内存(包含年轻代及年老代)

后记:

断断续续写了4天,也就憋出这点,本来还想写写回收算法,但考虑到自己也不是太了解,所以暂时放弃了,还有一些想写的不知道从何写起,以后有机会可能会再回来补充.不过好歹对自己以前的碎片知识简单做了整理,感觉收获还是蛮大的.