### JVM学习笔记 #### JVM内存模型 (JMM) JVM内存模型主要分为以下几个部分: - **Java堆**:这是所有线程共享的一块区域,在虚拟机启动时创建。主要用于存放对象实例,几乎所有的对象实例都在这里分配内存。 - **直接内存**:这部分内存并不属于JVM管理的内存的一部分,它由`NIO`类通过`sun.misc.Unsafe`的API直接分配。它的大小不受`-Xmx`的影响,而是受到本机总内存的限制。 - **Java栈**:每个线程拥有一个独立的Java栈,用于存储局部变量、操作数栈、动态链接、方法出口等信息。当线程被创建时,Java栈也会随之创建。 - **本地方法栈**:类似于Java栈,但为虚拟机使用到的Native方法服务。 - **方法区**:存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量池等内容。 - **类加载子系统**:负责读取并加载类文件信息到JVM中。 - **PC寄存器**:每个线程拥有一个独立的PC寄存器,用于记录当前线程所执行的字节码指令地址。 - **执行引擎**:负责解释执行或编译执行JVM字节码文件。 #### Java堆 Java堆是JVM中最为重要的内存区域之一,其主要用来存储对象实例。为了提高垃圾回收效率,通常会将堆划分为不同的区域,例如**新生代**和**老年代**。新生代进一步分为**Eden**区和两个**Survivor**区(S0、S1)。大多数对象都是在Eden区中创建的,当进行垃圾回收时,存活的对象会被移动到Survivor区之一。若对象在Survivor区中存活了一段时间(由具体的实现决定),则会被移动到老年代中。 #### Java栈 Java栈是每个线程私有的内存空间,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。其中,局部变量表用于保存函数的参数以及方法内部的局部变量,这些变量会在方法结束时销毁;操作数栈用于保存计算过程中的中间结果及变量的临时存储空间。 - **局部变量表**:是栈帧的重要组成部分,用于保存函数的参数以及方法内部的局部变量。局部变量表中的槽位如果超过了作用域是可以被复用的。 - **操作数栈**:用于保存计算过程中的中间结果,同时作为变量临时的存储空间。 #### 栈上分配 栈上分配是一种优化技术,它允许将对象分配在栈而不是堆上。这可以通过开启逃逸分析来实现,逃逸分析判断对象的作用域,如果确定对象不会被其他线程访问,则可以在栈上分配。这种方法减少了垃圾收集的压力,提高了程序的执行效率。 #### 方法区 方法区(在Java 8中称为元数据区)用于存储类信息,包括类的方法、字段、常量池等。在Java 8之前,可以通过`-XX:PermSize=xx`和`-XX:MaxPermSize=xx`来设置其大小,而在Java 8中则使用`-XX:MaxMetaspaceSize`来指定最大元数据区的大小。 #### 常用JVM参数 - **GC日志相关**: - `-XX:+PrintGC`:打印GC信息。 - `-XX:+PrintGCDetails`:打印详细的GC信息。 - `-XX:+PrintHeapAtGC`:在每次GC后打印堆的状态。 - `-XX:+PrintGCTimeStamps`:打印GC时间戳。 - `-Xloggc:log/gc.log`:将GC日志输出到文件。 - `-XX:+PrintGCApplicationConcurrentTime`:打印应用程序的执行时间。 - `-XX:+PrintGCApplicationStoppedTime`:打印应用程序由于GC产生的停顿时间。 - **跟踪类加载/卸载**: - `-verbose:class`:打印类加载/卸载信息。 - `-XX:+TraceClassLoading`:跟踪类加载。 - `-XX:+TraceClassUnloading`:跟踪类卸载。 - **查看系统参数**: - `-XX:+PrintVMOptions`:打印命令行显式指定的参数。 - `-XX:+PrintCommandLineFlags`:打印JVM显式或隐式的参数。 - `-XX:+PrintFlagsFinal`:打印所有的系统参数。 - **堆相关**: - `-Xmn512m`:设置新生代的大小为512M。 - `-XX:SurvivorRatio=8`:设置Eden/Survivor区的大小比为8:1。 - `-XX:NewRatio=2`:设置老年代/新生代的大小比为2:1。 - **栈相关**: - `-Xss512k`:设置每个线程的栈大小为512K。 - **直接内存**: - `-XX:MaxDirectMemorySize`:设置直接内存的最大值。 - **工作模式**: - `-server`:适用于服务器环境。 - `-client`:适用于客户端环境。 #### 垃圾回收算法 - **标记清除法**:标记不再使用的对象,然后进行清理。这种方法可能会导致内存碎片化问题。 - **复制算法**:将内存分成相等的两块,每次只使用其中一块,在垃圾回收时,将活着的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。这种方式的缺点是浪费了一半的空间。 - **标记压缩法**:在标记完成后,让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。这样可以避免内存碎片的产生。 - **分代算法**:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,这样可以有针对性地进行垃圾回收。 - **分区算法**:G1回收器将整个堆分为多个大小相同的独立区域,这种回收器可以灵活选择回收哪些区域。 #### 垃圾回收器 - **串行回收器**: - **新生代串行回收器**:使用单线程进行垃圾回收,适合单CPU的环境,实现简单且成熟。 - **老年代串行回收器**:同样使用单线程进行垃圾回收,但由于老年代对象较多,因此回收时间较长。 以上概述了JVM的主要组成部分及其相关的知识点,对于理解JVM的工作原理和优化有着重要的意义。
剩余8页未读,继续阅读
- 粉丝: 2
- 资源: 20
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助