您的位置:首页 > 编程语言 > Java开发

Jvm以及Jvm性能参数优化

2016-04-03 22:53 281 查看

一,Java虚拟机基本结构:



类加载子系统:  负责从文件系统或者网络中加载Class信息

方法区:  有时也称为永久区, 用于存放加载的类信息, 以及存放运行时常量池(包括字符串和数字常量, 这部份常量信息是Class文件中常量池部分的内存映射), java8开始称为元数据区, 设置参数也有所不一样

Java堆:  虚拟机启动时建立, 是Java程序最主要的内存工作区域, 几乎所有对象都会存放在Java堆中, 堆是所有线程共享的

直接内存:  Java的NIO库允许Java程序使用直接内存(例: DirectByteBuffer, 每次创建和释放都要调用System.gc()), 直接内存是Java堆外直接向系统申请的内存区间, 直接内存的访问优于堆,直接内存不受限于xmx的值, 不过受限于系统的最大内存

垃圾回收系统:  可以对Java堆,直接内存和方法区进行回收, 垃圾回收是隐式的自动完成的, 不用程序手动是释放内存

Java栈:  每个虚拟机线程都有私有的Java栈, 一个线程的栈是在线程创建时创建的, 栈中保存帧, 局部变量, 方法参数 , -Xss用于指定Java栈的空间大小

本地方法栈:  类似Java栈, 用于本地方法的调用, 是Java虚拟机的重要扩展, 即JNI, Java本地接口的调用, 通常是C或C++

PC寄存器:  也被为程序计数器, 是每个线程私有的空间, Java线程正在执行的方法如果不是本地方法, PC寄存器就会指向当前正在被执行的指令, 反之, PC寄存器的值是undefined

执行引擎:  Java虚拟核心组件之一, 负责执行虚拟机的字节码, 现代虚拟机的即时编译会将方法编译成机器码后再执行, 会提高执行效率

二,Java虚拟机参数设置:

(1)性能参数:

-server

  以server模式运行时将拥有:更大、更高的并发处理能力,更快更强捷的JVM垃圾回收机制,可以获得更多的负载与吞吐量

-Xmx

  指定java程序的最大堆内存, 使用java -Xmx5000M -version判断当前系统能分配的最大堆内存

-Xms

  指定最小堆内存, 通常设置成跟最大堆内存一样,减少GC

-Xmn

  设置年轻代大小为512m。整个堆大小=年轻代大小 + 年老代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

-Xss

  指定线程的最大栈空间, 此参数决定了java函数调用的深度, 值越大调用深度越深, 若值太小则容易出栈溢出错误(StackOverflowError)

设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程 大约需要占用多少内存,可能会有多少线程同时运行等。一般不易设置超过1M,要不然容易出现out ofmemory

-XX:PermSize

  指定方法区(永久区)的初始值,默认是物理内存的1/64, 在Java8永久区移除, 代之的是元数据区, 由-XX:MetaspaceSize指定

-XX:MaxPermSize

  指定方法区的最大值, 默认是物理内存的1/4, 在java8中由-XX:MaxMetaspaceSize指定元数据区的大小

-XX:NewRatio=n

  年老代与年轻代的比值,-XX:NewRatio=2, 表示年老代与年轻代的比值为2:1

-XX:SurvivorRatio=n

  Eden区与Survivor区的大小比值,-XX:SurvivorRatio=8表示Eden区与Survivor区的大小比值是8:1:1,因为Survivor区有两个(from, to)

-XX:+DoEscapeAnalysis

  开启逃逸分析, 逃逸分析的目的是判断对象的作用域是否可能逃逸出函数体, 逃逸分析是栈上分配的技术基础,对于非逃逸对象而言就是一个局部变量, 而对象未发生逃逸时, 虚拟机就有可能进行线上分配, 不是堆上, 栈上分配速度快,并且能避免垃圾回收带来的负面影响, 栈上分配是虚拟机提供的很好的对象分配优化策略

-XX:+EliminateAllocations

  开启标量替换(默认打开), 即允许对象打散分配在栈上, 即对象的属性视为独立局部变量进行分配到栈上

-XX:+UseCompressedOops

  开启指针压缩

-XX:+AggressiveOpts

  启用JVM开发团队最新的调优成果。例如编译优化,偏向锁,并行年老代收集等

  

-XX:-UseTLAB

  关闭TLAB , 默认是打开的

-Djava.awt.headless=true

  有时我们会在我们的J2EE工程中使用一些图表工具如:jfreechart,用于在web网页输出GIF/JPG等流,在winodws环境下,一般我 们的app server在输出图形时不会碰到什么问题,但是在linux/unix环境下经常会碰到一个exception导致你在winodws开发环境下图片显 示的好好可是在linux/unix下却显示不出来,因此加上这个参数以免避这样的情况出现.

-XX:+DisableExplicitGC

  在程序代码中不允许有显示的调用”System.gc()”。看到过有两个极品工程中每次在DAO操作结束时手动调用System.gc()一下,觉得这 样做好像能够解决它们的out ofmemory问题一样,付出的代价就是系统响应时间严重降低,就和我在关于Xms,Xmx里的解释的原理一样,这样去调用GC导致系统的JVM大起大 落,性能不到什么地方去哟!

-XX:+UseBiasedLocking

  偏向锁,启用一个优化了的线程锁,我们知道在我们的appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁使得你的appserver内对线程处理自动进行最优调配。

(2)垃圾回收相关:

Jvm垃圾回收器详细

(3)调试参数:

-verbose:gc

  表示输出虚拟机中GC的详细情况

-Xloggc:

  指定gc以文件输出(默认在控制台), 后面跟日志文件路径

-XX:+PrintGC

  加上参数可以在输出日志中可以查看垃圾回收前后堆的大小, 即打印gc日志

-XX:+PrintGCDetails

  打印gc日志的更加详细的信息

-XX:+PrintHeapAtGC

  打印每次GC前后堆的信息

-XX:+PrintGCTimeStamps

  输出GC发生时,gc发生的时间

-XX:+PrintGCApplicationConcurrentTime

  打印应用程序的执行时间

-XX:+PrintGCApplicationStoppedTime

  可以打印应用程序由于GC而产生的停顿时间

-XX:+PrintReferenceGC

  跟踪系统内的软引用,弱引用,虚引用和Finallize队列

-XX:+TraceClassLoading

  打印类加载时的相关信息

  

三, Java堆:

1, 堆内存(heap)和 Permanent区。

(1)Java堆内存(heap):

  –是 JVM 用于分配 Java 对象的内存,包含活动对象和不可用对象

  –堆大小通常是在服务器启动时使用 java 命令中的 –Xms(最小) –Xmx(最大)标志来定义。

(2)Permanent区:(永久区)

  –指内存的永久保存区域

  –是Sun JDK和HP JDK用来加载类(class)和Meta信息的专门的内存区

  –这个区域不归属Java堆内存(heap)范围

  –Class在被Loader时就会被放到此,如果Java应用很大,例如类(class)很多,那么建议增大这个区域的大小来满足加载这些类的内存需求

  –通过–XX:PermSize=***M –XX:MaxPermSize=***M调整

2, Java堆的结构:(新生代+老年代)



      


如上图, 如果 -Xms指定的值比-Xmx的小,那么两者的差值就是Virtual内存值。随着程序的运行,Eden区、 Tenured区和Perm区会逐渐使用保留的Virtual空间。

Young Generation 新生代, 即图中的Eden + From Space + To Space

Eden 存放新生的对象

Survivor Space 有两个,存放每次垃圾回收后存活的对象

Old Generation Tenured Generation 老年代, 即图中的Old Space 主要存放应用程序中生命周期长的存活对象

Jvm相关书籍推荐:<<实战Java虚拟机—JVM故障诊断与性能优化 >>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  虚拟机 jvm java