美文网首页
Java内存区域

Java内存区域

作者: 风暴预言家 | 来源:发表于2020-08-28 11:07 被阅读0次

    Java内存区域

    一. 运行时数据区域

    数据区域

    1. 程序计数器

      当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取吓一跳需要执行的字节码指令。需要注意的是:==如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)方法,这个计数器值则应为空==。此内存区域是唯一一个在《Java虚拟机规范》中没有规定任何OutOfMemortError情况的区域。

    2. Java虚拟机栈

      它的生命周期和线程相同。描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完毕的过程,都对应着一个栈帧在虚拟机占中从入栈到出站的过程。

    3.本地方法栈

      类似于虚拟机栈,其区别只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为了虚拟机使用到本地(Native)方法服务。有的虚拟机(比如hotspot)直接就把本地方法栈和虚拟机栈合二为一。

    4.Java堆

      是所有线程共享的一块内存区域,在虚拟机启动时创建。此区域唯一的目的就是存放对象实例,Java世界里"几乎"所有的对象实例都在这里分配内存。"几乎"是从实现角度来看的,随着Java语言的发展,现在已经能看到那些许迹象表明日后可能出现值类型的支持,即使只考虑现在,由于即时编译技术的进步,尤其是逃逸分析技术的日渐强大,栈上分配,标量替换优化手段已经导致一些微妙的变化悄然发生,所以Java对象实例都分配在对象也渐渐变得不那么绝对了。由于现代垃圾收集大部分都是基于分代收集理论设计的,许多资料上经常写着"Java虚拟机的堆内存分为新生代,老年代,永久代......"这样的内容,但是这些区域的划分仅仅是一部分垃圾收集器的共同特性或者说设计风格而已,而非某个Java虚拟机具体实现的固有内容布局,更不是《Java虚拟机规范》里对Java堆的进一步细致划分.
      如果从内存分配的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区(TLAB),以提升对象分配时的效率。

    5.方法区

      别名:非堆。永久代曾经是方法区的一种实现方式,当时的hotspot虚拟机设计团队选择把收集器的分代设计扩展至方法区,或者说使用永久代来实现方法区而已。考虑到hotspot未来的发展,在JDK6的时候HosSpot开发团队就有放弃永久代,逐步改为采用本地内存(Native Memory)来实现方法区的计划,到了JDK7的HotSpot,已经把原本放在永久代的字符串常量池[1]、静态变量等移出,而到了JDK8,终于完全放弃了永久代的概念,改用JRockit、J9一样的本地内存中实现元空间(Metaspace)来替代。
      《Java虚拟机规范》对方法区的约束是非常宽松的,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,甚至还可以选择不实现垃圾收集。

    6.运行时常量池

      方法区的一部分,Class文件中的常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。对于此区域,《Java虚拟机规范》并没有做任何细节的要求,不过一般来说,除了保存Class文件中描述的符号引用外,还会把由符号引用翻译出来的直接引用也存储在运行时常量池中。
      运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译器才能产生,也就是说,并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可以将新的常量放入池中,这种特性被开发人员利用的比较多的便是String类的intern()方法。

    7.直接内存

      直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。但是这部分内存也被频繁的使用,而且也可能导致OutOfMemoryError异常出现。
      在JDK1.4中新加入了NIO类,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象做为这块内存的引用进行操作(零拷贝)。


    1. 字符串常量池移到了Java堆中

    相关文章

      网友评论

          本文标题:Java内存区域

          本文链接:https://www.haomeiwen.com/subject/gqtlsktx.html