`

JVM 数据存储介绍及性能优化

阅读更多

转自http://www.ibm.com/developerworks/cn/java/j-lo-JVM-Optimize/index.html

JVM 内存模式介绍

Java 虚拟机内存模型是 Java 程序运行的基础。为了能使 Java 应用程序正常运行,JVM 虚拟机将其内存数据分为程序计数器、虚拟机栈、本地方法栈、Java 堆和方法区等部分。

程序计数器 (Program Counter Register)

程序计数器 (Program Counter Register) 是一块很小内存空间,由于 Java 是支持线程的语言,当线程数量超过 CPU 数量时,线程之间根据时间片轮询抢夺 CPU 资源。对于单核 CPU 而言,每一时刻只能有一个线程在运行,而其他线程必须被切换出去。为此,每一个线程都必须用一个独立的程序计数器,用于记录下一条要运行的指令。各个线程之间的计数器互不影响,独立工作,是一块线程独有的内存空间。如果当前线程正在执行一个 Java 方法,则程序计数器记录正在执行的 Java 字节码地址,如果当前线程正在执行一个 Native 方法,则程序计数器为空。

虚拟机栈

虚拟机栈用于存放函数调用堆栈信息。Java 虚拟机栈也是线程私有的内存空间,它和 Java 线程在同一时间创建,它保存方法的局部变量、部分结果,并参与方法的调用和返回。

Java 虚拟机规范允许 Java 栈的大小是动态的或者是固定的。在 Java 虚拟机规范中定义了两种异常与栈空间有关:StackOverflowError 和 OutOfMemoryError。如果线程在计算过程中,请求的栈深度大于最大可用的栈深度,则抛出 StackOverflowError;如果 Java 栈可以动态扩展,而在扩展栈的过程中没有足够的内存空间来支持栈的发展,则抛出 OutOfMemeoryError。可以使用-Xss 参数来设置栈的大小,栈的大小直接决定了函数调用的可达深度。

下面的例子展示了一个递归调用的应用。计数器 count 记录了递归的层次,这个没有出口的递归函数一定会导致栈溢出。程序则在栈溢出时,打印出栈的当前深度。

清单 1. 递归调用显示栈的最大深度
public class TestStack {
 private int count = 0;
 //没有出口的递归函数
 public void recursion(){
 count++;//每次调用深度加 1
 recursion();//递归
 }
 
 public void testStack(){
 try{
 recursion();
 }catch(Throwable e){
 System.out.println("deep of stack is "+count);//打印栈溢出的深度
 e.printStackTrace();
 }
 }
 
 public static void main(String[] args){
 TestStack ts = new TestStack();
 ts.testStack();
 }
}
清单 2. 清单 1 运行结果
java.lang.StackOverflowError
at TestStack.recursion(TestStack.java:7)
at TestStack.recursion(TestStack.java:7)
at TestStack.recursion(TestStack.java:7)
at TestStack.recursion(TestStack.java:7)
at TestStack.recursion(TestStack.java:7)
at TestStack.recursion(TestStack.java:7)
at TestStack.recursion(TestStack.java:7)deep of stack is 9013

虚拟机栈在运行时使用一种叫做栈帧的数据结构保存上下文数据。在栈帧中,存放了方法的局部变量表、操作数栈、动态连接方法和返回地址等信息。每一个方法的调用都伴随着栈帧的入栈操作。相应地,方法的返回则表示栈帧的出栈操作。如果方法调用时,方法的参数和局部变量相对较多,那么栈帧中的局部变量表就会比较大,栈帧会膨胀以满足方法调用所需传递的信息。因此,单个方法调用所需的栈空间大小也会比较多。

函数嵌套调用的次数由栈的大小决定。栈越大,函数嵌套调用次数越多。对一个函数而言,它的参数越多,内部局部变量越多,它的栈帧就越大,其嵌套调用次数就会减少。

本地方法栈

本地方法栈和 Java 虚拟机栈的功能很相似,本地方法栈用于存放函数调用堆栈信息。Java 虚拟机栈用于管理 Java 函数的调用,而本地方法栈用于管理本地方法的调用。本地方法并不是用 Java 实现的,而是使用 C 实现的。在 SUN 的 HotSpot 虚拟机中,不区分本地方法栈和虚拟机栈。因此,和虚拟机栈一样,它也会抛出 StackOverflowError 和 OutofMemoryError。

Java 堆

堆用于存放 Java 程序运行时所需的对象等数据。几乎所有的对象和数组都是在堆中分配空间的。Java 堆分为新生代和老生代两个部分,新生代用于存放刚刚产生的对象和年轻的对象,如果对象一直没有被回收,生存得足够长,老年对象就被移入老年代。新生代又可进一步细分为 eden、survivor space0 和 survivor space1。eden 即对象的出生地,大部分对象刚刚建立时都会被存放在这里。survivor 空间是存放其中的对象至少经历了一次垃圾回收,并得以幸存下来的。如果在幸存区的对象到了指定年龄仍未被回收,则有机会进入老年代 (tenured)。下面例子演示了对象在内存中的分配方式。

清单 3. 进行一次新生代 GC
public class TestHeapGC {
 public static void main(String[] args){
 byte[] b1 = new byte[1024*1024/2];
 byte[] b2 = new byte[1024*1024*8];
 b2 = null;
 b2 = new byte[1024*1024*8];//进行一次新生代 GC
 System.gc();
 }
}
清单 4. 清单 3 的配置
-XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -Xms40M -Xmx40M -Xmn20M
清单 5. 清单 3 的输出
[GC [DefNew: 9031K->661K(18432K), 0.0022784 secs] 9031K->661K(38912K),
   0.0023178 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
 Heap
 def new generation total 18432K, used 9508K [0x34810000, 0x35c10000, 0x35c10000)
 eden space 16384K, 54% used [0x34810000, 0x350b3e58, 0x35810000)
 from space 2048K, 32% used [0x35a10000, 0x35ab5490, 0x35c10000)
 to space 2048K, 0% used [0x35810000, 0x35810000, 0x35a10000)
 tenured generation total 20480K, used 0K [0x35c10000, 0x37010000, 0x37010000)
 the space 20480K, 0% used [0x35c10000, 0x35c10000, 0x35c10200, 0x37010000)
 compacting perm gen total 12288K, used 374K [0x37010000, 0x37c10000, 0x3b010000)
 the space 12288K, 3% used [0x37010000, 0x3706db10, 0x3706dc00, 0x37c10000)
 ro space 10240K, 51% used [0x3b010000, 0x3b543000, 0x3b543000, 0x3ba10000)
 rw space 12288K, 55% used [0x3ba10000, 0x3c0ae4f8, 0x3c0ae600, 0x3c610000)

上述输出显示 JVM 在进行多次内存分配的过程中,触发了一次新生代 GC。在这次 GC 中,原本分配在 eden 段的变量 b1 被移动到 from 空间段 (s0)。最后分配的 8MB 内存被分配在 eden 新生代。

方法区

方法区用于存放程序的类元数据信息。方法区与堆空间类似,它也是被 JVM 中所有的线程共享的。方法区主要保存的信息是类的元数据。方法区中最为重要的是类的类型信息、常量池、域信息、方法信息。类型信息包括类的完整名称、父类的完整名称、类型修饰符和类型的直接接口类表;常量池包括这个类方法、域等信息所引用的常量信息;域信息包括域名称、域类型和域修饰符;方法信息包括方法名称、返回类型、方法参数、方法修饰符、方法字节码、操作数栈和方法栈帧的局部变量区大小以及异常表。总之,方法区内保持的信息大部分来自于 class 文件,是 Java 应用程序运行必不可少的重要数据。

在 Hot Spot 虚拟机中,方法区也称为永久区,是一块独立于 Java 堆的内存空间。虽然叫做永久区,但是在永久区中的对象同样也可以被 GC 回收的。只是对于 GC 的表现也和 Java 堆空间略有不同。对永久区 GC 的回收,通常主要从两个方面分析:一是 GC 对永久区常量池的回收;二是永久区对类元数据的回收。Hot Spot 虚拟机对常量池的回收策略是很明确的,只要常量池中的常量没有被任何地方引用,就可以被回收。

清单 6 所示代码会生成大量 String 对象,并将其加入常量池中。String.intern() 方法的含义是如果常量池中已经存在当前 String,则返回池中的对象,如果常量池中不存在当前 String 对象,则先将 String 加入常量池,并返回池中的对象引用。因此,不停地将 String 对象加入常量池会导致永久区饱和。如果 GC 不能回收永久区的这些常量数据,那么就会抛出 OutofMemoryError 错误。

清单.6 GC 收集永久区
public class permGenGC {
 public static void main(String[] args){
 for(int i=0;i<Integer.MAX_VALUE;i++){
 String t = String.valueOf(i).intern();//加入常量池
 }
 }
}
清单 7. 清单 6 的配置
-XX:PermSize=2M -XX:MaxPermSize=4M -XX:+PrintGCDetails
清单 8. 清单 6 的输出
[Full GC [Tenured: 0K->149K(10944K), 0.0177107 secs] 3990K->149K(15872K),
   [Perm : 4096K->374K(4096K)], 0.0181540 secs] [Times: user=0.02 sys=0.02, real=0.03 secs] 
[Full GC [Tenured: 149K->149K(10944K), 0.0165517 secs] 3994K->149K(15936K),
[Perm : 4096K->374K(4096K)], 0.0169260 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 
[Full GC [Tenured: 149K->149K(10944K), 0.0166528 secs] 3876K->149K(15936K),
[Perm : 4096K->374K(4096K)], 0.0170333 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

每当常量池饱和时,FULL GC 总能顺利回收常量池数据,确保程序稳定持续进行。

JVM 参数调优实例

由于 Java 字节码是运行在 JVM 虚拟机上的,同样的字节码使用不同的 JVM 虚拟机参数运行,其性能表现可能各不一样。为了能使系统性能最优,就需要选择使用合适的 JVM 参数运行 Java 应用程序。

设置最大堆内存

JVM 内存结构分配对 Java 应用程序的性能有较大的影响。

Java 应用程序可以使用的最大堆可以用-Xmx 参数指定。最大堆指的是新生代和老生代的大小之和的最大值,它是 Java 应用程序的堆上限。清单 9 所示代码是在堆上分配空间直到内存溢出。-Xmx 参数的大小不同,将直接决定程序能够走过几个循环,本例配置为-Xmx5M,设置最大堆上限为 5MB。

清单 9 .Java 堆分配空间
import java.util.Vector;

public class maxHeapTest {
 public static void main(String[] args){
 Vector v = new Vector();
 for(int i=0;i<=10;i++){
 byte[] b = new byte[1024*1024];
 v.add(b);
 System.out.println(i+"M is allocated");
 }
 System.out.println("Max memory:"+Runtime.getRuntime().maxMemory());
 }
}
清单 10. 运行输出
0M is allocated
1M is allocated
2M is allocated
3M is allocated
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at maxHeapTest.main(maxHeapTest.java:8)

此时表明在完成 4MB 数据分配后系统空闲的堆内存大小已经不足 1MB 了。

设置 GC 新生代区大小

参数-Xmn 或者用于 Hot Spot 虚拟机中的参数-XX:NewSize(新生代初始大小)、-XX:MaxNewSize 用于设置新生代的大小。设置一个较大的新生代会减小老生代的大小,这个参数对系统性能以及 GC 行为有很大的影响。新生代的大小一般设置为整个堆空间的 1/4 到 1/3 左右。

以清单 9 的代码为例,若使用 JVM 参数-XX:+PrintGCDetails -Xmx11M -XX:NewSize=2M -XX:MaxNewSize=2M -verbose:gc 运行程序,将新生代的大小减小为 2MB,那么 MinorGC 次数将从 4 次增加到 9 次 (默认情况下是 3.5MB 左右)。

清单 11. 运行输出
[GC [DefNew: 1272K->150K(1856K), 0.0028101 secs] 1272K->1174K(11072K),
   0.0028504 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC [DefNew: 1174K->0K(1856K), 0.0018805 secs] 2198K->2198K(11072K),
0.0019097 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
clearing....
[GC [DefNew: 1076K->0K(1856K), 0.0004046 secs] 3274K->2198K(11072K),
0.0004382 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC [DefNew: 1024K->0K(1856K), 0.0011834 secs] 3222K->3222K(11072K),
0.0013508 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC [DefNew: 1024K->0K(1856K), 0.0012983 secs] 4246K->4246K(11072K),
0.0013299 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
clearing....
[GC [DefNew: 1024K->0K(1856K), 0.0001441 secs] 5270K->4246K(11072K),
0.0001686 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC [DefNew: 1024K->0K(1856K), 0.0012028 secs] 5270K->5270K(11072K),
0.0012328 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC [DefNew: 1024K->0K(1856K), 0.0012553 secs] 6294K->6294K(11072K),
0.0012845 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
clearing....
[GC [DefNew: 1024K->0K(1856K), 0.0001524 secs] 7318K->6294K(11072K),
0.0001780 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 def new generation total 1856K, used 1057K [0x36410000, 0x36610000, 0x36610000)
 eden space 1664K, 63% used [0x36410000, 0x365185a0, 0x365b0000)
 from space 192K, 0% used [0x365e0000, 0x365e0088, 0x36610000)
 to space 192K, 0% used [0x365b0000, 0x365b0000, 0x365e0000)
 tenured generation total 9216K, used 6294K [0x36610000, 0x36f10000, 0x37010000)
 the space 9216K, 68% used [0x36610000, 0x36c35868, 0x36c35a00, 0x36f10000)
 compacting perm gen total 12288K, used 375K [0x37010000, 0x37c10000, 0x3b010000)
 the space 12288K, 3% used [0x37010000, 0x3706dc88, 0x3706de00, 0x37c10000)
 ro space 10240K, 51% used [0x3b010000, 0x3b543000, 0x3b543000, 0x3ba10000)
 rw space 12288K, 55% used [0x3ba10000, 0x3c0ae4f8, 0x3c0ae600, 0x3c610000)

设置持久代大小

持久代 (方法区) 不属于堆的一部分。在 Hot Spot 虚拟机中,使用-XX:MaxPermSize 参数可以设置持久代的最大值,使用-XX:PermSize 可以设置持久代的初始大小。持久代的大小直接决定了系统可以支持多少个类定义和多少常量。对于使用 CGLIB 或者 Javassit 等动态字节码生成工具的应用程序而言,设置合理的持久代大小有助于维持系统稳定。系统所支持的最大类与 MaxPermSize 成正比。一般来说,MaxPermSize 设置为 64MB 已经可以满足绝大部分应用程序正常工作。如果依然出现永久区溢出,可以设置为 128MB。这是两个很常用的永久区取值。如果 128MB 依然不能满足应用程序需求,那么对于大部分应用程序来说,则应该考虑优化系统的设计,减少动态类的产生,或者利用 GC 回收部分驻扎在永久区的无用类信息,以使系统健康运行。

设置线程栈大小

线程栈是线程的一块私有空间。在 JVM 中可以使用-Xss 参数设置线程栈的大小。

在线程中进行局部变量分配,函数调用时都需要在栈中开辟空间。如果栈的空间分配太小,那么线程在运行时可能没有足够的空间分配局部变量或者达不到足够的函数调用深度,导致程序异常退出;如果栈空间过大,那么开设线程所需的内存成本就会上升,系统所能支持的线程总数就会下降。由于 Java 堆也是向操作系统申请内存空间的,因此,如果堆空间过大,就会导致操作系统可用于线程栈的内存减少,从而间接减少程序所能支持的线程数量。

清单 12 所示代码尝试开设尽可能多的线程,并在线程数量饱和时,打印已经开设的线程数量。

清单 12. 尝试开启尽可能多的线程
public class TestXss {
 public static class MyThread extends Thread{
 @Override
 public void run(){
 try{
 Thread.sleep(10000);
 }catch(InterruptedException e){
 e.printStackTrace();
 }
 }
 }
 
 public static void main(String[] args){
 int count=0;
 try{
 for(int i=0;i<10000;i++){
 new MyThread().start();
 count++;
 }
 }catch(OutOfMemoryError e){
 System.out.println(count);
 System.out.println(e.getMessage());
}
 }
}
清单 13. 配置-Xss1M 时的运行输出
1578
unable to create new native thread

一共允许启动 1578 个线程。

清单 14. 配置-Xss20M 时的运行输出
69
unable to create new native thread

实验证明如果改变系统的最大堆空间设定,可以发现系统所能支持的线程数量也会相应改变。

Java 堆的分配以 200MB 递增,当栈大小为 1MB 时,最大线程数量以 200 递减。当系统物理内存被堆占据时,就不可以被栈使用。当系统由于内存空间不够而无法创建新的线程时会抛出 OOM 异常。这并不是由于堆内存不够而导致的 OOM,而是因为操作系统内存减去堆内存后剩余的系统内存不足而无法创建新的线程。在这种情况下可以尝试减少堆内存以换取更多的系统空间来解决这个问题。综上所述,如果系统确实需要大量线程并发执行,那么设置一个较小的堆和较小的栈有助于提高系统所能承受的最大线程数。

设置堆的比例分配

参数-XX:SurvivorRatio 是用来设置新生代中 eden 空间和 s0 空间的比例关系。s0 和 s1 空间又分别称为 from 空间和 to 空间。它们的大小是相同的,职能也是相同的,并在 Minor GC 后互换角色。

清单 15. 所示示例演示不断插入字符时使用的 GC 输出
import java.util.ArrayList;
import java.util.List;

public class StringDemo {
 public static void main(String[] args){
 List<String> handler = new ArrayList<String>();
 for(int i=0;i<1000;i++){
 HugeStr h = new HugeStr();
 ImprovedHugeStr h1 = new ImprovedHugeStr();
 handler.add(h.getSubString(1, 5));
 handler.add(h1.getSubString(1, 5));
 }
 }
 
 static class HugeStr{
 private String str = new String(new char[800000]);
 public String getSubString(int begin,int end){
 return str.substring(begin, end);
 }
 }
 
 static class ImprovedHugeStr{
 private String str = new String(new char[10000000]);
 public String getSubString(int begin,int end){
 return new String(str.substring(begin, end));
 }
 }
}

清单 16. 设置新生代堆为 10MB,并使 eden 区是 s0 的 8

-XX:+PrintGCDetails -XX:MaxNewSize=10M -XX:SurvivorRatio=8
清单 17. 运行输出
[Full GC [Tenured: 233756K->233743K(251904K), 0.0524229 secs] 233756K->233743K(261120K),
[Perm : 377K->372K(12288K)], 0.0524703 secs] [Times: user=0.06 sys=0.00, real=0.06 secs] 
def new generation total 9216K, used 170K [0x27010000, 0x27a10000, 0x27a10000)
 eden space 8192K, 2% used [0x27010000, 0x2703a978, 0x27810000)
 from space 1024K, 0% used [0x27910000, 0x27910000, 0x27a10000)
 to space 1024K, 0% used [0x27810000, 0x27810000, 0x27910000)
 tenured generation total 251904K, used 233743K [0x27a10000, 0x37010000, 0x37010000)
 the space 251904K, 92% used [0x27a10000, 0x35e53d00, 0x35e53e00, 0x37010000)
 compacting perm gen total 12288K, used 372K [0x37010000, 0x37c10000, 0x3b010000)
 the space 12288K, 3% used [0x37010000, 0x3706d310, 0x3706d400, 0x37c10000)
 ro space 10240K, 51% used [0x3b010000, 0x3b543000, 0x3b543000, 0x3ba10000)
rw space 12288K, 55% used [0x3ba10000, 0x3c0ae4f8, 0x3c0ae600, 0x3c610000)

修改参数 SurvivorRatio 为 2 运行程序,相当于设置 eden 区是 s0 的 2 倍大小,由于 s1 与 s0 相同,故有 eden=[10MB/(1+1+2)]*2=5MB。

清单 18. 运行输出
[Full GC [Tenured: 233756K->233743K(251904K), 0.0546689 secs] 233756K->233743K(259584K),
   [Perm : 377K->372K(12288K)],0.0547257 secs] [Times: user=0.05 sys=0.00, real=0.05 secs] 
def new generation total 7680K, used 108K [0x27010000, 0x27a10000, 0x27a10000)
 eden space 5120K, 2% used [0x27010000, 0x2702b3b0, 0x27510000)
 from space 2560K, 0% used [0x27510000, 0x27510000, 0x27790000)
 to space 2560K, 0% used [0x27790000, 0x27790000, 0x27a10000)
 tenured generation total 251904K, used 233743K [0x27a10000, 0x37010000, 0x37010000)
 the space 251904K, 92% used [0x27a10000, 0x35e53d00, 0x35e53e00, 0x37010000)
 compacting perm gen total 12288K, used 372K [0x37010000, 0x37c10000, 0x3b010000)
 the space 12288K, 3% used [0x37010000, 0x3706d310, 0x3706d400, 0x37c10000)
 ro space 10240K, 51% used [0x3b010000, 0x3b543000, 0x3b543000, 0x3ba10000)
rw space 12288K, 55% used [0x3ba10000, 0x3c0ae4f8, 0x3c0ae600, 0x3c610000)

Java 堆参数总结

Java 堆操作是主要的数据存储操作,总结的主要参数配置如下。

与 Java 应用程序堆内存相关的 JVM 参数有:

-Xms:设置 Java 应用程序启动时的初始堆大小;

-Xmx:设置 Java 应用程序能获得的最大堆大小;

-Xss:设置线程栈的大小;

-XX:MinHeapFreeRatio:设置堆空间最小空闲比例。当堆空间的空闲内存小于这个数值时,JVM 便会扩展堆空间;

-XX:MaxHeapFreeRatio:设置堆空间的最大空闲比例。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的堆;

-XX:NewSize:设置新生代的大小;

-XX:NewRatio:设置老年代与新生代的比例,它等于老年代大小除以新生代大小;

-XX:SurvivorRatio:新生代中 eden 区与 survivor 区的比例;

-XX:MaxPermSize:设置最大的持久区大小;

-XX:TargetSurvivorRatio: 设置 survivor 区的可使用率。当 survivor 区的空间使用率达到这个数值时,会将对象送入老年代。

结束语

从所有这些参数描述信息和代码示例可以看到,没有哪一条固定的规则可以供程序员参考。性能优化需要根据您应用的实际情况来有选择性地挑选参数及配制值,没有完全绝对的最优方案,最优方案是基于您对 JVM 数据存储方式及自己代码的了解程度来作出的最佳选择。

分享到:
评论

相关推荐

    实战JAVA虚拟机 JVM故障诊断与性能优化

    《实战JAVA虚拟机—JVM故障诊断与性能优化》是一...总之,《实战JAVA虚拟机—JVM故障诊断与性能优化》这本书全面地介绍了JVM的相关知识,无论你是开发者还是运维人员,都能从中受益匪浅,提升你在Java领域的专业技能。

    java jvm及性能优化_javajvm优化_Java性能分析_

    以下是对"Java JVM及性能优化"和"Java性能分析"的详细阐述: 一、JVM结构与工作原理 1. 类装载器:负责加载类文件,确保在运行时能找到对应的类。 2. 运行数据区:包括方法区、堆、栈、本地方法栈和程序计数器。...

    JVM性能优化(PPT)

    **JVM性能优化** 在Java开发中,JVM(Java Virtual Machine)是至关重要的组成部分,它负责运行所有的Java应用程序。JVM性能优化是一项细致而关键的任务,能够显著提升程序的运行效率,减少资源消耗,提高系统稳定...

    redis集群jvm调优实战MySQL5.6性能优化&Tomcat7优化.rar

    本资料集围绕四个核心主题展开:Redis集群、JVM调优、MySQL 5.6性能优化和Tomcat 7的优化,旨在帮助开发者和运维人员更好地理解和实践这些关键领域的优化策略。 首先,Redis是一个高性能的键值存储系统,常用于缓存...

    实战Java虚拟机——JVM故障诊断与性能优化

    《实战Java虚拟机——JVM故障诊断与性能优化》是一本深入探讨Java开发人员和运维人员必备技能的书籍。本书作者葛一鸣以其丰富的实战经验,详细阐述了JVM(Java Virtual Machine)的工作原理,以及如何有效地进行故障...

    JVM性能优化相关问题.pdf

    本次分享的内容将涵盖Java类的加载过程、类加载机制、内存分配和垃圾收集机制等关键知识点,这些内容对于理解Java程序的性能优化至关重要。 首先,我们来探讨Java类加载的过程,这个过程包括了加载、验证、准备、...

    Jvm性能优化-JVM内存结构原理分析03

    "Jvm性能优化-JVM内存结构原理分析03" Jvm性能优化是Java虚拟机(JVM)中非常重要的一部分,它对Jvm的性能产生了很大的影响。本文将从Jvm内存结构的角度来分析Jvm性能优化的原理。 Jvm内存结构主要分为五部分:堆...

    JVM和性能优化学习思维笔记_swim5we_jvm_性能优化_

    在Java开发领域,JVM(Java Virtual Machine)和性能优化是至关重要的主题。这份"JVM和性能优化学习思维笔记"旨在帮助开发者深入理解和实践Java应用程序的性能提升。以下是基于标题、描述和标签所涉及的知识点的详细...

    JVM内存模型和性能优化.docx

    然而,JVM的性能优化往往需要关注对象的生命周期管理。不当的对象生命周期处理可能导致内存溢出或者性能下降。开发者需要从需求出发,识别具有自然边界的业务对象,并将它们映射到内存中的In-memory Domain Model,...

    JVM和性能优化1

    前端优化可以改善用户感知,应用服务性能优化包括缓存和集群等技术,存储性能优化则关注数据读写效率。JVM层面的优化涉及JIT编译器、GC调优等,例如选择合适的垃圾回收器、调整堆大小、减少Full GC的发生等。 总结...

    JVM性能优化:线程锁优化.docx

    Java虚拟机(JVM)性能优化的一个重要领域是线程锁优化,这直接影响到多线程应用程序的效率和并发性能。线程锁是确保多线程环境下数据一致性和线程安全的关键机制。以下是对线程锁优化的一些核心知识点的详细说明: ...

    Tomcat性能优化及JVM内存工作原理

    【标题】:深入理解Tomcat性能优化与JVM内存工作原理 【正文】: Tomcat作为一款广泛应用的Java Servlet容器,其性能优化对于提升Web应用的响应速度和稳定性至关重要。而JVM(Java Virtual Machine)内存管理是...

    深入JVM内核—原理、诊断与优化视频教程-2.JVM运行机制

    6. **内存溢出和性能优化**:理解内存泄漏和内存溢出的原因,如堆内存不足、栈溢出等,以及如何通过调整JVM参数进行性能优化,如设置堆大小、开启并发收集、优化新生代和老年代的比例等。 7. **异常处理与线程调度*...

    深入JVM内核—原理、诊断与优化视频教程-3.常用JVM配置参数

    深入理解JVM的内核原理、诊断技巧以及优化方法对于提升应用性能至关重要。本教程——“深入JVM内核—原理、诊断与优化视频教程”,将重点讲解这些关键点,帮助开发者提升技术水平,更好地解决实际问题。 首先,我们...

    深入jvm 内核-原理,诊断于优化视频教程

    jstat是一个命令行工具,用于收集JVM的实时性能数据,如堆内存使用情况、GC活动等。虽然它没有图形界面,但使用起来非常灵活。 #### 五、案例分析与实践 **5.1 实战案例** - **案例1:电商网站性能瓶颈定位**:...

    JVM与性能优化知识点整理.pdf

    JVM的性能优化是提升Java应用效率的关键环节,涉及到内存管理、垃圾收集、线程调度等多个方面。** 一、JVM内存结构 1. **堆内存**:Java对象的主要存储区域,分为新生代和老年代,新生代又细分为Eden区和两个...

    Spark大数据处理数据性能优化学习

    Spark采用了内存计算模型,它将数据存储在内存中,从而实现了快速的数据处理。RDD(Resilient Distributed Datasets)是Spark的基础数据结构,它是不可变的、分区的、并行的数据集,可以跨集群节点分布。RDD支持转换...

Global site tag (gtag.js) - Google Analytics