JVM分为四部分
Class Loader 类加载器:实质是把类文件从硬盘读取到内存中,只要符合文件结构就加载,至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。
Execution Engine 执行引擎:执行引擎也叫做解释器(Interpreter) ,负责解释命令,提交操作系统执行。
Native Interface本地接口:调用其它语言库。
Runtime data area 运行时数据区:整个JVM 的重点。我们所有写的程序都被加载到这里,之后才开始运行。程序有一些随虚拟机的启动而创建,随虚拟机的退出而销毁;另一些与线程一一对应,随线程的开始和结束而创建和销毁。概括地说来,JVM初始运行的时候都会分配好 Method Area(方法区) 和Heap(堆) ,而JVM 每遇到一个线程,就为其分配一个 Program Counter Register(程序计数器) , VM Stack(虚拟机栈)和Native Method Stack (本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来说知发生在Heap上)的原因。
补充说明
栈是运行时的单位,而堆是存储的单位。
栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,即数据怎么放、放在哪儿。
在Java中一个线程就会相应有一个线程栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同因此需要一个独立的线程栈。而堆则是所有线程共享的【因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的】。栈因为是运行单位,因此里面存储的信息都是跟当线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值等等;而堆只负责存储对象信息。堆中存的是对象。栈中存的是基本数据类型和堆中对象的引用。
堆和栈中,栈是程序运行最根本的东西。程序运行可以没有堆,但是不能没有栈。而堆是为栈进行数据存储服务,说白了堆就是一块共享的内存。不过,正是因为堆和栈的分离的思想,才使得Java的垃圾回收成为可能。
栈的大小通过-Xss来设置,当栈中存储数据比较多时,需要适当调大这个值,否则会出现java.lang.StackOverflowError异常。常见的出现这个异常的是无法返回的递归,因为此时栈中保存的信息都是方法返回的记录点。
堆内存设置【其中New和Tenured属于堆内存,堆内存会从JVM启动参数-Xms -Xmx指定的内存中分配,Perm不属于堆内存,由虚拟机直接分配,但可以通过-XX:PermSize -XX:MaxPermSize 等参数调整其大小】;
垃圾回收器
新生代收集器:Serial,ParNew,Parallel Scavenge;老年代收集器:Serial Old;CMS;Parallel Old;堆内存垃圾收集器:G1
示例
Java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -jar test(java程序)
-Xmx3550m:设置JVM最大可用内存为3550M。
-Xms3550m:设置JVM初始内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0 –jar test(java程序)
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
-XX:MaxPermSize=16m:设置非堆最大内存为16m。
-XX:+PrintFlagsInitial 显示所有可设置参数及默认值
-XX:+PrintFlagsFinal 显示所有可设置参数修改后的值
-XX:+PrintCommandLineFlags 显示出JVM初始化完毕后所有跟最初的默认值不同的参数及它们的值
可在/usr/local/apache-tomcat-*/bin 目录下的catalina.sh 文件cygwin=false上面一行添加:
JAVA_OPTS='-Xms512m -Xmx1024m'
或者JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
或者CATALINA_OPTS="-server -Xms256m -Xmx300m"
检测
常用命令:JPS ,JSTAT,JMAP,JINFO
jstat -gcutil pid 命令查看GC情况
jstat –gccapacity pid
jmap -heap pid 查看JVM堆占用情况
jinfo –flags pid