第二章 java内存区域与内存溢出异常
2.2 运行时数据区域

1.程序计数器:为了线程切换后能恢复到正确的执行位置,每个线程都需要有一个独立的程序计数器,(线程私有内存)注:唯一一个没有规定任何内存溢出异常(OutOfMemoryError)情况的区域
2.java虚拟机栈:java方法在执行的同时创建的一个栈帧(用于存储局部变量表等),也就是常常提到的栈内存。 局部变量表的空间在编译期间完成分配

3.本地方法栈(Native Method Stack):给非java语言使用的虚拟机栈;有些虚拟机将两者合二为一(Sun HotSpot虚拟机,就是最常用的那个)
4.java堆:存放对象实例、数组,是被所有线程共享的一块内存区域,在虚拟机启动时创建。“GC堆”,垃圾收集器管理的主要区域。
5.方法区:各线程共享的内存区域。存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码(我理解是动态生成的反射类)。hotSpot虚拟机在JDK1.7之前,将永久代来实现方法区,1.8之后使用元数据来实现方法区。
6.运行时常量池:属于方法区的一部分,存放编译期间生成的字面量和符号引用,在类加载时放到常量池中;此区域具有动态性,最长用到的是String.inern()方法
7.直接内存(堆外内存):此内存不属于JVM,但是此内存如果超出了最大限定也会抛出OOM异常。此内存是由于NIO类的产生。

图解:
1.检测是否能在常量池中定位到此类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
2.分配内存的两种方式:
指针碰撞;
空闲列表。
选择哪种方式取决于java堆是否规整,而java堆是否规整又取决于垃圾收集器是否存在压缩规整功能。
解决分配内存时线程不安全的两种方式:
CAS+失败重试;
本地线程分配缓冲(TLAB)。
3.保证了对象的实例字段在Java代码中可以不赋初始值就直接使用

对象的访问方式:句柄和直接指针。HotSpot虚拟机采用直接指针,因为速度快。
本文详细介绍了Java运行时数据区域,包括程序计数器、虚拟机栈、本地方法栈、堆、方法区、运行时常量池以及直接内存。其中,堆和方法区是可能出现内存溢出异常的主要区域。对象的分配方式、线程安全问题以及访问对象的两种方式也进行了阐述。同时,直接内存虽非JVM一部分,但过度使用同样可能导致OOM异常。
385

被折叠的 条评论
为什么被折叠?



