### 学习笔记之Java虚拟机详解 #### 运行时数据区域概览 Java虚拟机(JVM)运行时数据区域主要包括以下几部分:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区以及运行时常量池。 1. **程序计数器**: - 用于记录当前线程所执行的字节码指令地址。 - 当执行的是Java方法时,程序计数器记录的是当前线程所执行的字节码指令地址。 - 对于native方法,程序计数器的值为空(Undefined),表示此时该线程执行的是非Java语言(如C/C++)编写的本地方法。 2. **Java虚拟机栈**: - 每个线程在创建时都会创建一个栈,用于存储线程私有的栈帧。 - 栈帧包含了局部变量表、操作数栈、动态链接信息及方法返回地址等信息。 - 主要用于支持Java方法的执行。 3. **本地方法栈**: - 类似于Java虚拟机栈,但是服务于本地方法调用。 - 具体实现方式取决于具体的虚拟机实现。 - 主要用于支持native方法的执行。 4. **Java堆**: - Java堆是所有线程共享的一块内存区域,主要用来存放对象实例。 - 包括了所有的对象实例和数组。 - 垃圾收集器的主要管理区域,负责清理不再使用的对象。 - 物理上可以是不连续的内存空间,但在逻辑上被视为连续。 5. **方法区**: - 存储已被虚拟机加载的类信息、常量、静态变量等数据。 - 可选择实现垃圾回收机制。 - 在HotSpot虚拟机中,通常被称为“永久代”。 6. **运行时常量池**: - 是方法区的一部分,用于存放编译期间产生的各种字面量和符号引用。 - 支持在程序运行期间添加新的常量。 - 不同于传统意义上的常量池,其内容可能会随着程序的执行而变化。 7. **直接内存**: - 直接内存不属于虚拟机运行时数据区域的一部分,而是通过Native方法直接分配的堆外内存。 - 用于提高某些特定场景下的性能,如NIO中的Buffer。 #### HotSpot虚拟机对象探秘 - **对象创建**: - 新建对象时,首先检查new指令的参数是否能在常量池中找到对应的类符号引用,并确保该类已经被加载、解析和初始化。 - 分配内存的方式有两种:指针碰撞和空闲列表。 - 在并发环境下,内存分配可能会采用CAS+失败重试或本地线程分配缓冲(TLAB)机制来保证安全性。 - **对象的内存布局**: - 包括对象头、实例数据和对齐填充三部分。 - 对象头包含运行时数据和类型指针,用于标记对象的状态和指向类元数据的信息。 - 实例数据存储对象的实际信息。 - 对齐填充是为了让对象大小符合特定的字节数对齐规则。 - **对象的访问定位**: - 可以通过句柄或直接指针的方式访问对象。 - 句柄方式的优点是在对象移动时无需修改java栈中的信息。 - 直接指针方式更快速,因为它减少了寻址的过程。 #### OutOfMemoryError 异常 - **内存泄漏**: - 内存泄漏是指分配出去的内存无法被回收的情况。 - Java中常见的内存泄漏通常是由于不再使用的对象仍然保持着可达状态。 - **内存溢出**: - 内存溢出是指程序请求的内存超过了系统能够提供的范围。 - 在Java中,通常表现为堆溢出或栈溢出。 #### 对象已死的判定 - **引用计数算法**: - 虽然简单直观,但在处理对象间的循环引用问题时表现不佳。 - 因此,在现代Java虚拟机中并未使用此算法。 - **可达性分析算法**: - 以根对象(如虚拟机栈中的局部变量、方法区中的静态变量等)作为起点,通过引用链遍历对象图。 - 如果从根对象开始搜索不到某个对象,就认为该对象不可达,从而可被垃圾回收。 以上是关于Java虚拟机的一些基础知识和深入理解的内容。通过对这些知识点的学习和掌握,可以帮助开发者更好地理解和优化Java程序的性能。
剩余16页未读,继续阅读
- 粉丝: 0
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助