Java之JVM的知识点有哪些

发布时间:2022-07-13 10:54:42 作者:iii
来源:亿速云 阅读:119

Java之JVM的知识点有哪些

目录

  1. JVM概述
  2. JVM内存结构
  3. 类加载机制
  4. 垃圾回收机制
  5. JVM调优
  6. JVM工具
  7. JVM常见问题
  8. 总结

JVM概述

Java虚拟机(JVM)是Java平台的核心组件之一,它负责执行Java字节码。JVM的主要功能包括加载类文件、执行字节码、管理内存、执行垃圾回收等。JVM的设计目标是提供一个与平台无关的执行环境,使得Java程序可以在任何支持JVM的平台上运行。

JVM的架构包括以下几个主要部分: - 类加载器(Class Loader):负责加载类文件到JVM中。 - 运行时数据区(Runtime Data Areas):包括方法区、堆、栈、本地方法栈和程序计数器。 - 执行引擎(Execution Engine):负责执行字节码。 - 本地方法接口(Native Method Interface):提供与本地代码的交互。 - 垃圾回收器(Garbage Collector):负责自动回收不再使用的内存。

JVM内存结构

方法区

方法区(Method Area)是JVM内存结构中的一部分,用于存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区是线程共享的内存区域,所有线程都可以访问其中的数据。

方法区的大小可以通过JVM参数进行配置: - -XX:PermSize:设置方法区的初始大小。 - -XX:MaxPermSize:设置方法区的最大大小。

在Java 8及以后的版本中,方法区被元空间(Metaspace)所取代。元空间使用本地内存来存储类元数据,不再受限于JVM的内存限制。

堆(Heap)是JVM内存结构中最大的一部分,用于存储对象实例和数组。堆是线程共享的内存区域,所有线程都可以访问堆中的数据。

堆的大小可以通过JVM参数进行配置: - -Xms:设置堆的初始大小。 - -Xmx:设置堆的最大大小。

堆可以分为新生代(Young Generation)和老年代(Old Generation): - 新生代:用于存放新创建的对象。新生代又可以分为Eden区、Survivor区(From和To)。 - 老年代:用于存放经过多次垃圾回收后仍然存活的对象。

栈(Stack)是JVM内存结构中的一部分,用于存储线程的局部变量、方法调用和返回值。每个线程都有自己的栈,栈是线程私有的内存区域。

栈的大小可以通过JVM参数进行配置: - -Xss:设置每个线程的栈大小。

栈可以分为以下几个部分: - 局部变量表:用于存储方法中的局部变量。 - 操作数栈:用于存储操作数和中间结果。 - 动态链接:用于支持方法调用。 - 方法返回地址:用于存储方法返回后的执行地址。

本地方法栈

本地方法栈(Native Method Stack)是JVM内存结构中的一部分,用于支持本地方法(Native Method)的执行。本地方法栈与栈类似,但它是为本地方法服务的。

本地方法栈的大小可以通过JVM参数进行配置: - -Xoss:设置本地方法栈的大小。

程序计数器

程序计数器(Program Counter Register)是JVM内存结构中的一部分,用于存储当前线程执行的字节码指令的地址。程序计数器是线程私有的内存区域,每个线程都有自己的程序计数器。

程序计数器的大小是固定的,通常为4字节或8字节。

类加载机制

类加载过程

类加载过程是JVM将类文件加载到内存中并生成对应的Class对象的过程。类加载过程包括以下几个步骤:

  1. 加载(Loading):通过类加载器将类文件加载到内存中。
  2. 验证(Verification):验证类文件的字节码是否符合JVM规范。
  3. 准备(Preparation):为类的静态变量分配内存并设置初始值。
  4. 解析(Resolution):将类文件中的符号引用转换为直接引用。
  5. 初始化(Initialization):执行类的静态初始化代码和静态变量赋值。

类加载器

类加载器(Class Loader)是JVM中负责加载类文件的组件。JVM中有以下几种类加载器:

  1. 启动类加载器(Bootstrap Class Loader):负责加载JVM核心类库,如java.lang.*等。
  2. 扩展类加载器(Extension Class Loader):负责加载JVM扩展类库,如javax.*等。
  3. 应用程序类加载器(Application Class Loader):负责加载应用程序类路径(Classpath)中的类。
  4. 自定义类加载器(Custom Class Loader):用户自定义的类加载器,可以加载特定路径下的类。

类加载器采用双亲委派模型(Parent Delegation Model)来加载类。双亲委派模型的工作流程如下: 1. 当一个类加载器收到类加载请求时,首先将请求委派给父类加载器。 2. 如果父类加载器无法加载该类,则由当前类加载器尝试加载。

双亲委派模型的好处是可以避免类的重复加载,确保类的唯一性。

垃圾回收机制

垃圾回收算法

垃圾回收(Garbage Collection, GC)是JVM自动管理内存的机制,用于回收不再使用的对象所占用的内存。JVM中有以下几种常见的垃圾回收算法:

  1. 标记-清除算法(Mark-Sweep)

    • 标记:从根对象(如栈中的引用、静态变量等)开始,标记所有可达的对象。
    • 清除:遍历整个堆,清除未被标记的对象。
    • 缺点:会产生内存碎片。
  2. 复制算法(Copying)

    • 将内存分为两个区域,每次只使用其中一个区域。
    • 当进行垃圾回收时,将存活的对象复制到另一个区域,然后清空当前区域。
    • 优点:不会产生内存碎片。
    • 缺点:内存利用率较低。
  3. 标记-整理算法(Mark-Compact)

    • 标记:从根对象开始,标记所有可达的对象。
    • 整理:将存活的对象向一端移动,然后清理边界以外的内存。
    • 优点:不会产生内存碎片,内存利用率高。
    • 缺点:整理过程耗时较长。
  4. 分代收集算法(Generational Collection)

    • 将堆分为新生代和老年代,分别采用不同的垃圾回收算法。
    • 新生代通常采用复制算法,老年代通常采用标记-清除或标记-整理算法。
    • 优点:根据对象的生命周期采用不同的回收策略,提高回收效率。

垃圾回收器

JVM中有以下几种常见的垃圾回收器:

  1. Serial收集器

    • 单线程垃圾回收器,适用于单核CPU环境。
    • 新生代采用复制算法,老年代采用标记-整理算法。
  2. Parallel收集器

    • 多线程垃圾回收器,适用于多核CPU环境。
    • 新生代采用复制算法,老年代采用标记-整理算法。
  3. CMS收集器(Concurrent Mark Sweep)

    • 并发垃圾回收器,适用于对响应时间要求较高的应用。
    • 新生代采用复制算法,老年代采用标记-清除算法。
    • 优点:减少垃圾回收的停顿时间。
    • 缺点:会产生内存碎片。
  4. G1收集器(Garbage-First)

    • 面向服务端应用的垃圾回收器,适用于大内存、多核CPU环境。
    • 将堆划分为多个区域(Region),每个区域可以是新生代或老年代。
    • 采用标记-整理算法,优先回收垃圾最多的区域。
    • 优点:减少垃圾回收的停顿时间,内存利用率高。

JVM调优

内存调优

内存调优是JVM调优的重要组成部分,主要目的是合理分配内存资源,避免内存溢出(OOM)和内存泄漏。以下是一些常见的内存调优参数:

GC调优

GC调优是JVM调优的另一个重要方面,主要目的是减少垃圾回收的停顿时间,提高应用的响应速度。以下是一些常见的GC调优参数:

JVM工具

jps

jps是JVM提供的一个命令行工具,用于查看当前系统中运行的Java进程的PID和主类名。使用jps命令可以快速定位Java进程。

jps

jstat

jstat是JVM提供的一个命令行工具,用于监控JVM的内存和GC情况。jstat可以显示堆内存、新生代、老年代、元空间等的使用情况。

jstat -gc <pid>

jmap

jmap是JVM提供的一个命令行工具,用于生成Java堆的内存快照(Heap Dump)。jmap可以用于分析内存泄漏问题。

jmap -dump:format=b,file=heapdump.hprof <pid>

jstack

jstack是JVM提供的一个命令行工具,用于生成Java线程的堆栈跟踪信息。jstack可以用于分析死锁问题。

jstack <pid>

jconsole

jconsole是JVM提供的一个图形化工具,用于监控JVM的内存、线程、类加载、GC等情况。jconsole可以通过JMX连接到远程JVM进行监控。

jconsole

VisualVM

VisualVM是JVM提供的一个功能强大的图形化工具,集成了jconsolejmapjstack等工具的功能。VisualVM可以用于监控JVM的性能、分析内存泄漏、分析线程问题等。

jvisualvm

JVM常见问题

内存泄漏

内存泄漏(Memory Leak)是指程序中不再使用的对象仍然占用内存,导致内存无法被回收。内存泄漏会导致内存使用量不断增加,最终可能导致OOM。

常见的内存泄漏原因包括: - 静态集合类持有对象的引用。 - 未关闭的资源(如数据库连接、文件流等)。 - 监听器未注销。

OOM

OOM(Out Of Memory)是指JVM无法分配足够的内存来满足程序的需求。OOM通常是由于内存泄漏或内存配置不合理导致的。

常见的OOM类型包括: - java.lang.OutOfMemoryError: Java heap space:堆内存不足。 - java.lang.OutOfMemoryError: PermGen space:方法区内存不足(Java 8之前)。 - java.lang.OutOfMemoryError: Metaspace:元空间内存不足(Java 8及以后)。 - java.lang.OutOfMemoryError: unable to create new native thread:无法创建新的线程。

死锁

死锁(Deadlock)是指多个线程相互等待对方释放资源,导致所有线程都无法继续执行。死锁通常是由于线程竞争资源不当导致的。

常见的死锁原因包括: - 多个线程持有对方需要的锁。 - 锁的获取顺序不一致。

总结

JVM是Java平台的核心组件之一,理解JVM的内存结构、类加载机制、垃圾回收机制等知识点对于Java开发者来说非常重要。通过合理的内存调优和GC调优,可以提高应用的性能和稳定性。同时,掌握JVM工具的使用可以帮助开发者快速定位和解决JVM相关的问题。

在实际开发中,JVM的调优和问题排查是一个复杂的过程,需要结合具体的应用场景和性能需求进行分析和调整。希望本文的内容能够帮助读者更好地理解和掌握JVM的相关知识。

推荐阅读:
  1. Java之Spring知识点
  2. java JVM原理与常识知识点

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java jvm

上一篇:python DataFrame的合并方法有哪些

下一篇:Python爬虫解析器BeautifulSoup4怎么使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》