java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > jvm调优

JVM调优实战

作者:旧言.

本文主要介绍了JVM调优实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.为什么需要进行JVM调优?

假设我们有一个简单的Java应用程序,它处理大量的数据并进行复杂的计算。在运行过程中,我们观察到应用程序的响应时间逐渐增加,并且在某些情况下会出现长时间的停顿。为了找出问题的根源,通过分析堆栈日志,我们可以了解每个线程在执行过程中的状态和行为,从而找到性能瓶颈和潜在的问题。

"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f8e04001800 nid=0x5103 waiting on condition [0x000070000e2ef000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.example.MyApp.processData(MyApp.java:45)
        at com.example.MyApp.run(MyApp.java:23)
        at java.lang.Thread.run(Thread.java:748)

"Thread-2" #13 prio=5 os_prio=0 tid=0x00007f8e04002000 nid=0x5203 waiting on condition [0x000070000e3f2000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.example.MyApp.processData(MyApp.java:45)
        at com.example.MyApp.run(MyApp.java:23)
        at java.lang.Thread.run(Thread.java:748)

"Thread-3" #14 prio=5 os_prio=0 tid=0x00007f8e04002800 nid=0x5303 waiting on condition [0x000070000e4f5000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076af8aeb8> (a java.util.concurrent.CountDownLatch$Sync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:

997)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
        at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
        at com.example.MyApp.processData(MyApp.java:60)
        at com.example.MyApp.run(MyApp.java:23)
        at java.lang.Thread.run(Thread.java:748)

从堆栈日志中,我们可以得到以下信息:

通过分析堆栈日志,我们可以发现以下问题和优化点:

通过分析堆栈日志,可以深入了解应用程序在运行过程中的行为和性能瓶颈。这有助于我们定位和解决问题,进而进行JVM调优以提升应用程序的性能和稳定性。

2.什么情况下可能需要JVM调优

堆内存持续增长:如果应用程序的堆内存持续增长并且接近或达到了最大内存限制(由 -Xmx 参数设置),这可能表明存在内存泄漏或者内存使用不合理的情况,需要进行调优来优化内存使用。

频繁的Full GC:如果应用程序中频繁发生Full GC,即对整个堆进行回收的情况,这可能会导致较长的停顿时间和性能下降。调优的目标是尽量减少Full GC的次数。

垃圾回收停顿时间过长:如果垃圾回收的停顿时间超过了可接受的范围(一般认为超过1秒),可能会影响应用程序的响应性能和用户体验。调优的目标是减小垃圾回收的停顿时间。

内存异常:如果应用程序经常遇到内存异常,如OutOfMemoryError,表明应用程序的内存使用超出了JVM的限制,需要调优来提高内存的利用率和稳定性。

大量占用内存的本地缓存:如果应用程序中使用了大量的本地缓存,并且占用了大量的内存空间,可能会导致内存不足的问题。调优的目标是优化缓存策略和内存管理,减少内存占用。

性能不佳或不稳定:如果应用程序的吞吐量和响应性能不高或不稳定,可能是由于内存管理不当导致的。调优的目标是提高应用程序的性能和稳定性。

需要注意的是,进行JVM调优时需要根据具体情况进行分析和优化,同时要进行充分的测试和验证,以确保调优的效果和稳定性。

3.JVM调优参数

-Xms: 设置Java堆的初始大小。
-Xmx: 设置Java堆的最大大小。
-Xmn: 设置年轻代的大小。
-XX:NewRatio: 设置年轻代和老年代的大小比例。
-XX:SurvivorRatio: 设置Eden区和Survivor区的大小比例。
-XX:MaxPermSize(在Java 8及之前版本中使用)或-XX:MaxMetaspaceSize(在Java 8及以后版本中使用): 设置永久代(或元空间)的最大大小。
-XX:ParallelGCThreads: 设置并行垃圾回收的线程数。
-XX:ConcGCThreads: 设置并发标记垃圾回收的线程数。
-XX:+UseConcMarkSweepGC: 启用并发标记清除垃圾回收器。
-XX:+UseParallelGC: 启用并行垃圾回收器。
-XX:+UseG1GC: 启用G1垃圾回收器。
-XX:+UseCompressedOops: 启用压缩指针,减小对象引用的内存占用。
-XX:MaxGCPauseMillis: 设置垃圾回收的最大停顿时间目标。
-XX:+PrintGCDetails: 打印详细的垃圾回收日志。

启动jar包时可以通过参数来设置,如设置初始堆大小为512MB,最大堆大小为1024MB,年轻代和老年代的比例为3:1,并行垃圾回收线程数为4。

java -Xms512m -Xmx1024m -XX:NewRatio=3 -XX:ParallelGCThreads=4 -jar springboot.jar

除了命令行参数外,可以在应用程序代码使用System.setProperty()方法来动态设置JVM参数如:
设置并行处理的线程池大小为8

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "8");

4.JVM调优参数设置参考

堆内存大小:使用-Xms和-Xmx参数设置堆的最小和最大大小。通常将最小和最大设置为相同的值,以避免堆的收缩和扩展带来的额外开销。

年轻代和年老代大小比例:可以通过调整-XX:NewRatio参数来调整年轻代和年老代的大小比例。根据应用程序对象的生命周期分布和观察实际情况,选择合适的大小比例。

年轻代大小设置:使用-XX:NewSize和-XX:MaxNewSize参数设置年轻代的绝对大小。通常将这两个值设置为相同的大小,以避免年轻代的收缩。

年老代收集算法:在配置较好的机器上,可以选择并行收集算法来提高年老代的垃圾回收效率。使用-XX:+UseParallelOldGC参数启用并行年老代收集器。

线程堆栈大小:默认情况下,每个线程的堆栈大小为1MB。可以通过调整-Xss参数减小线程堆栈大小,以节省内存。

5.JVM内部结构

JVM(Java虚拟机)是Java程序运行的环境,它是一个虚拟的计算机,具有自己的内部结构和组件。

1. 类加载器(Class Loader)

类加载器负责将Java字节码文件加载到内存中,并将其转换为可执行的类。JVM使用了三个主要的类加载器:启动类加载器(Bootstrap Class Loader)、扩展类加载器(Extension Class Loader)和应用程序类加载器(Application Class Loader)。

2. 运行时数据区(Runtime Data Area)

3. 垃圾收集器(Garbage Collector)

垃圾收集器负责自动管理内存,回收不再使用的对象。JVM中有多种垃圾收集器可供选择,如Serial、Parallel、CMS(Concurrent Mark and Sweep)和G1(Garbage First)等。它们采用不同的算法和策略来进行垃圾回收。

4. 即时编译器(Just-In-Time Compiler,JIT)

即时编译器将Java字节码转换为本地机器代码,以提高程序的执行效率。JIT根据代码的热点(HotSpot)进行动态编译,将频繁执行的代码优化为本地机器代码。

5. 安全管理器(Security Manager)

安全管理器用于保护JVM和应用程序免受恶意代码的攻击。它负责检查和控制Java程序的访问权限,确保程序运行在安全的环境中。

6. JNI(Java Native Interface)

JNI允许Java程序调用本地方法,与底层系统交互。通过JNI,Java程序可以访问操作系统的功能和其他编程语言的库。

6.JVM 调优策略

1. 内存管理和垃圾回收优化

2. JIT编译器优化

3. 并发性优化

4. 使用工具进行分析和优化

到此这篇关于JVM调优实战的文章就介绍到这了,更多相关jvm调优 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文