new关键字发生了什么系列补充(Java内存结构)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fangmenghao/article/details/88130411

前言

这篇文章对应系列(二)而诞生,什么不会学什么。当初在学习的时候其实只是想有个线性的学习过程,但是书籍是做了系统的分模块介绍,并没有给我循序渐进的感觉。而且有时候与实际并没有太多的联系,很多环节不去想就不会对应了(但是还挺有趣)

根据Java虚拟机规范,定义了内存区域

0x01 程序计数器

线程私有(所以生命周期随线程而生死)

作用:线程从中获取所需要执行的字节码的行号指示器,如果执行的是本地方法栈方法则为null

异常:Java虚拟机规范没有规定任何OutOfMemoryError

0x02 Java虚拟机栈

线程私有

作用:描述java方法执行的内存模型,每个方法在执行时才会创建一个栈帧

所以一些方法需要的信息都会在栈帧中,一些参数也会在其中

异常:线程请求栈深度大于虚拟机允许的深度,抛出StackOverflowError,虚拟机栈可以动态扩展,如果扩展无法申请足够多的内存,抛出OutOfMemeoryError

0x03 本地方法栈

非线程私有

作用:类似Java虚拟机栈,提供本地的Native方法

异常:同Java虚拟机栈

0x04 Java堆

非线程私有

作用:存放对象实例的地方(大部分,但是随着逃逸分析技术、栈上分配、标量替换等新技术出现,也不是所有对象都在堆上分配)

异常:若没有内存分配对象实例,抛出OutOfMemeoryError

jvm参数:-Xmx最大值和-Xms最小值

根据垃圾收集算法,java堆还可以细分到Eden区和Survivor区,都是为了垃圾回收

0x05 方法区

非线程私有

作用:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

异常:抛出OutOfMemoryError异常

ps1:hotspot将其作为永久代,目的是为了将其与新生代、老年代一起做垃圾回收,可以理解为垃圾回收延长到了方法区(因为hotspot用永久代了实现方法区)
ps2:作为永久代来说,很容易遇到内存溢出问题,因为有少数方法在不同虚拟机下可能会用到永久代,所以可能导致内存溢出。比如String的intern方法

0x06 运行时常量池

非线程私有

作用:方法区的一部分,用于存放编译期生成的各种字面量和符号引用,具有动态性,程序运行期间也有可能将新变量放入常量池

异常:抛出OutOfMemoryError异常,受到方法区内存大小的限制

0x07 直接内存

非虚拟机运行时数据区的一部分

作用:nio有使用到

异常:抛出OutOfMemoryError异常

0xFF 总结

Java程序在启动的时候要分配线程去执行代码,那么这个时候这个线程拥有自己的内存空间(程序计数器、java虚拟机栈),然后会操作java堆中的内存(堆内存共享,所以多个人去搞同一个地方的东西是不是可能会出问题?当然终极原因还是因为硬件级别的问题)

这些内存空间只是为了存放程序运行时数据,而这些数据也不是一直存在的。所以为了方便回收这些不需要的数据(垃圾)才进行这些内存结构的划分

猜你喜欢

转载自blog.csdn.net/fangmenghao/article/details/88130411