浅谈Java之Java内存结构解析

一、前言

Java内存结构是我们作为Java工程师有必要掌握的理论知识之一。需要注意的是,我们常常谈及的Java内存结构其实准确来讲指的是JVM的内存结构,同时还需注意Java内存结构与Java内存模型的区别不要将二者混为一谈。

二、运行时数据区

分析JVM的内存结构主要就是分析运行时数据区,代码运行时JVM就会划分出几个数据区我们可以统称为运行时数据区,主要包括:方法区(Method Area)、堆(Heap)、本地方法栈(Native Stack)、虚拟机栈(JVM Stack)、程序计数器(Program Counter Register),其实质就是将连续的内存抽象为不同作用的内存区域。
在这里插入图片描述

1、方法区

方法区是线程共享的,可存放已被加载的类的信息、常量、静态变量、即时编译器编译后的代码缓存等。其主要结构包括:类的信息的存储区、运行时常量池、静态变量、即时编译后的代码。

运行时常量池存储的信息存储内容
常量(字面量)基本数据类型的值、字符串、final修饰的常量等
符号引用类或接口的全类名、方法名称及描述符、字段名称和描述符

注:常量池能够避免对象的频繁创建销毁,从而达到节约资源的目的。根据类型的不同有不同的常量池,如字符串常量池、Integer常量池(存放的常量为-128到127)等。
需要注意的是,jdk8开始方法区就被元空间所替代了,这使得本地内存能够被利用使其不再拘束于JVM的内存分配,这样能够有效避免因分配内存不足而引起的OutOfMemoryError异常(OMM异常),同时我们也可以设置元空间的大小来防止物理内存被过多地占用。

2、堆

Java堆用于存放所有的对象实例以及数组,同时也是垃圾收集器(Garbage Collection)进行垃圾回收的主要区域。
在堆中对对象有明确的划分,年轻代、老年代、永久代,需要注意的是永久代从jdk8开始就被取消并用元空间替代。对对象的分类主要是以这个对象的生命周期长短为依据的。
年轻代
年轻代为刚刚创建的对象实例,其又细分为Eden空间、Survivor0空间、Survivor1空间,两个Servivor区也可称为from/to区。新创建的对象会在Eden空间足够的情况下放入其中,若Eden空间不足就会触发GC对未被引用的对象进行回收(Minor GC),然后再放入的同时将之前已被引用的对象放入Servivor0区,若Servivor0区已满那么就会将本该移入Servivor0区的对象移入老年代区。Servivor0区在触发GC时也是同理将之前已被引用的对象放入Servivor1区中,两个Servivor区中的对象会不断“反复横跳”(这也是为什么Servivor区也叫from/to区的原因吧)直到其“年龄”过大后就会被移入老年代(年龄指的是经历GC的次数,超过15次时就为老年代)。
在这里插入图片描述
老年代
老年代区分配内存不足时也会被GC进行垃圾回收(Major GC),若进行垃圾回收后仍无法存放对象则会出现OMM异常。
永久代
永久代中存放的是字节码文件被加载后的信息,细心的朋友获或许注意到了方法区不是存储的也是类的信息吗?说到这里就不得不提及永久代与方法区之间的联系。方法区是JVM的一个规范,方法区在逻辑上属于堆的一部分,但又有所区别,因此方法区又被称为非堆(NO Heap)。这个规范是所有虚拟机必须遵守的,而永久代就是HotSpot虚拟机对方法区规范的一个具体实现,因此元空间既是方法区的替代也是永久代区的替代。

3、本地方法栈

凡是标有Native关键字的方法都会调用底层的C语言的库,用来对Java进行拓展。可以得知Native方法并不是Java语言编写的,而是由本地语言编写的能够直接与操作系统进行交互的。

4、虚拟机栈

与本地方法栈类似,我常常将其称为虚拟机方法栈(这样更能体现出其与本地方法栈类似但有区别),存放基本类型变量以及存放引用类型变量所指向的具体的地址存放本地方法表、操作栈、动态链接、方法出口等。
需要补充的是,我们都知道栈的特点就是只能从表的尾端也就是栈顶进行数据的插入和删除,在栈中存放的是栈帧,每一个栈帧中存放的才是局部变量表、操作数栈、方法出口等信息。方法的执行顺序和每个方法的执行流程大体上都由栈控制。

5、程序计数器

程序计数器能够记录当前线程接下来要执行的字节码的地址,同时程序计数器的线程私有保证了每个线程的指令的有序执行。当执行的是Native方法则程序计数器为undefined。

三、垃圾回收类型

Minor GC:作用于年轻代,当分配给Eden区的内存不足时触发。
Major GC:作用于老年代,当分配给老年代区内存不足时触发。
Full GC:整堆回收——作用于堆(包括方法区),通常老年代区或永久代区满了都会触发。

四、小结

以上是我个人对Java内存结构的简单总结,但想要真正理Java或者说JVM的内存结构,单靠这点总结显然是不够的,在之后我会更深入地对其进行了解。希望读者们不要因技术理论的晦涩难懂就轻易放弃,不积跬步无以至千里,一点点的积累才能有最后的收获。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值