虚拟机,通俗一点讲就是模拟一台真实机器环境。主要分为系统虚拟机和程序虚拟机。
系统虚拟机:Visual Box、Vmar
程序虚拟机:典型的就是Java虚拟机
Java虚拟机:HotSpot、Jrockit(现在都是oracle旗下的)
JVM内存结构主要有三大块:堆内存、方法区和栈。堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden空间、From Survivor空间、To Survivor空间,默认情况下年轻代按照8:1:1的比例来分配。
方法区:首先明确方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。JVM虚拟机规范把方法区描述为堆得要个逻辑部分。它的别名叫做Non-Heap(非堆)。目的是与堆区分开来。
Java堆:垃圾收集器的主要管理部分。也是Java虚拟机所管理的内存中最大的一块。是被所有线程共享的一块内存区域。在虚拟机启动时被创建。此区域主要用来存放对象的实例。几乎所有的对象的实例都在这里分配内存。主要分为新生代和老年代。新生代有可以细分为Eden区、from区、to区。
Java栈:线程的私有内存空间,每个方法被执行时候都会同事创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。方法的调用直至执行完成的过程。就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
本地方法栈:最大不同为本地方法栈用于本地方法调用。Java虚拟机允许Java直接调用本地方法(通过使用C语言写)
PC寄存器:程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器
垃圾收集系统是Java的核心,也是不可少的,Java有一套自己进行垃圾清理的机制,开发人员无需手工清理
Java虚拟机常见的内存调优参数
|
参数 |
含义 |
|
-XX:+PrintGC |
每次触发GC的时候打印相关日志 |
|
-XX:+PrintGCDetails |
更详细的GC日志 |
|
-Xms |
堆初始值 |
|
-Xmx |
堆得最大可用值 |
|
-Xmn |
新生代堆最大可用值 |
|
-XX:+UseSerialGC |
串行回收 |
|
-XX:SurvivorRatio |
用来设置新生代中eden空间和from/to空间的比例. |
|
-XX:NewRatio |
老年代/新生代比例 |
|
-XX:PermSize=10M |
表示JVM初始分配的永久代的容量,必须以M为单位 |
|
-verbose:gc |
表示输出虚拟机中GC的详细情况 |
|
-Xss128k |
表示可以设置虚拟机栈的大小为128k |
注意:
- 在实际应用中,我们可以将初始的堆大小与最大堆大小设置为相等,这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。
- 新生代和老年代的比例尽量设置在1/3或者1/2的比例
- Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)
- 如果有对象的年龄以及达到了老年的标准,一般是15,则赋值到老年代区
常见的问题解决
错误原因: java.lang.OutOfMemoryError: Java heap space
解决办法:增加堆内存
-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError
错误原因: java.lang.StackOverflowError
导致的原因:栈溢出 产生于递归调用,循环遍历是不会的,但是循环方法里面产生递归调用, 也会发生栈溢出。
解决办法:设置栈的最大深度 -Xss5m