JVMjava
一.虚拟机的基本结构算法
1.jvm总体架构sql
类加载子系统:负责从文件系统或者网络中加载class信息,存入方法区中。服务器
方法区(Perm):存放加载后的class信息,包括静态方法,jdk1.6之前包含了常量池。网络
参数:-XX:PermSize初始值 -XX:MaxPermSize最大值数据结构
Java堆(Heap):java工程的主要内存工做区域,全部线程共享,jdk1.7之后包含了常量池。参数: -Xms初始值 -Xmx最大值多线程
直接内存:java堆外,直接向系统申请的内存区间,容许NIO库使用。申请空间慢,读写快。默认下最大可用空间等于堆的最大可用空间。在server模式下,读写速度是堆的10倍。架构
参数:-XX:MaxDirectMemorySize 最大值jvm
垃圾回收器:函数
Java栈:线程私有,用于存放局部变量,方法参数,同时和java方法的调用返回密切相关。
参数:-Xss最大值
本地方法栈:和java栈相似,主要用于本地方法调用。
PC寄存器:线程私有
执行引擎:
Java [-options] class [args...]
其中-options是java虚拟机的启动参数,args是传递给main方法的参数、
2.java堆
根据垃圾回收机制的不一样,java堆有可能拥有不一样的结构,常见的java堆分为新生代和老年代。其中新生代存放刚建立的对象及年龄不大的对象,老年带存放着在新生代中经历过屡次回收后还存在的对象。
对象晋升过程:
新生代分为eden区s0,s1区(from,to)。多数状况下对象首先分配在eden区,在一次新生代回收后,存活下来的对象存入s0或s1区。每通过一次新生代的回收,对象的年龄加1。默认状况下年龄达到15的对象将晋升至老年代。若是在第一次回收的时候,存活的对象大于s0(s1)空间,将直接晋升至老年代,若是在为对象第一次分配空间时,对象空间大于eden空间的话,对象也直接分配到老年代。
3.java栈
Java栈和数据结构中的栈有着相似的含义,先进后出,只支持入栈和出栈操做。Java栈中保存的只要内容是栈帧,每一次进行函数调用,都会有一个对应的栈帧被压入栈中,函数调用结束,都会有一个栈帧被弹出栈。
栈帧
每个栈帧中包含局部变量表,操做数栈和帧数据区。
栈上分配
栈上分配的基本思想,是将线程私有的对象,打散分配到栈上,分配在栈上的函数调用结束后对象会自行销毁,不须要垃圾回收接入,从而提高性能。对于大量的零散小对象,栈上分配提供了一种很好的对象分配优化策略,但因为和堆空间相比,栈空间较小,所以大对象没法也不适合在栈上分配
栈上分配依赖逃逸分析和标量替换的实现,同时必须在server模式下才能启用。参数-XX:+DoEscapeAnalysis启用逃逸分析 -XX:+EliminateAllocations开启标量替换(默认打开).
例:-server -Xms 100m -Xmx 100m -XX:+DoEscapeAnalysis -XX:+EliminateAllocations
二.Jvm经常使用参数
1.GC参数
-XX:+PrintGC 每次触发GC的时候打印相关日志
-XX:+PrintGCDetails 更详细的GC日志
-XX:+PrintHeapAtGC 每次GC时打印堆的详细详细信息
-XX:+PrintGCApplicationConcurrentTime 打印应用程序执行时间
-XX:+PrintGCApplicationAtoppedTime 打印应用程序由GC引发的停顿时间
-XX:+PrintReferenceGC 跟踪系统内的软引用,弱引用,虚引用和finallize队列。
1.类跟踪
-verbose:class 跟踪类的加载和卸载
-XX:+TraceClassLoading 单独跟踪类加载
-XX:+TraceClassUnloading 单独跟踪类卸载
-XX:+PrintClassHistogram 查看运行时类的分布状况,使用时在控制台按ctrl+break
2.系统参数查看
-XX:+PrintVMOptions 运行时,打印jvm接受的命令行显式参数
-XX:+PrintCommandLineFlags 打印传递jvm的显式和隐式参数
-XX:+PrintFlagsFinal 打印全部系统参数值
3.堆
-Xms 堆初始值
-Xmx 堆最大可用值
-Xmn 新生代大小,通常设为整个堆的1/3到1/4左右
-XX:SurvivorRatio 设置新生代中eden区和from/to空间的比例关系n/1
-XX:NewRatio 设置老年代与新生代的比
想要合理的分配堆内存,须要了解对象的晋升过程,能够参照上面介绍堆空间架构时,对对象晋升过程的描述。
基本策略:堆的不一样分布状况,对系统会产生必定的影响。尽量将对象预留在新生代,减小老年代GC的次数(一般老年回收起来比较慢)。实际工做中,一般将堆的初始值和最大值设置相等,这样能够减小程序运行时进行的垃圾回收次数和空间扩展,从而提升程序性能。
4.非堆
-XX:PermSize 方法区(永久区)初始值
-XX:MaxPermSize 方法区(永久区)最大值
-Xss 设置栈空间大小
-XX:MaxDirectMemorySize 直接内存最大可用空间,设置不当可能致使系统OOM
5.虚拟机工做模式
-client 默认工做模式
-server server工做模式,启动虚拟机时须要显式指定
与client模式相比,server模式启动较慢,会尝试搜集更多的系统性能信息,使用更复杂的优化算法对程序进行优化,server模式下系统彻底启动并进入稳按期后,执行速度远远快于client模式,适合长期后台运行的系统。Client模式更适合运行时间不长,又追求启动速度的客户端程序。
三.Jvm性能监控工具
1.JConsole
内存监控,线程监控,类加载状况,虚拟机信息
2.Visual VM
线程dump和分析,性能分析,内存快照分析,BTrace
3.Mission Control
MBean服务器,飞行记录器
四.分析java堆
1.常见的内存溢出缘由及解决思路
(1)堆溢出:设置-Xmx调整最大可用堆空间
(2)直接内存溢出:多是系统内存空间不足,同时没达到参数默认的上限,没有触发GC致使OOM,解决方法是经过-XX:MaxDirectMemorySize 来限制最大内存。
(3)过多线程致使OOM:因为每开启一个线程都会给这个线程分配一个栈,所以当线程数达到必定程度,系统空间不足的时候就会内存溢出,能够尝试减小堆空间,或者能够经过设置参数-Xss限制每一个栈的大小。
(4)永久区溢出:系统加载的类过多,致使永久区溢出,经过-XX:MaxPermSize来设置永久区最大可用空间。
(5)GC效率低下引发的OOM:GC是内存回收的关键,回收效率低颇有可能引发内存溢出,能够经过合理的分配堆(包括新生代和老年代)空间去解决。
2.String形成的内存泄漏
内存泄漏是指,再也不使用的对象占据内存不释放,致使可用内存不断减少,最终引发内存泄漏。在Java1.6中String.subString()方法就存在这样的问题。
SubString中新生成的对象并无从value中获取本身须要的那部分,而是直接简单的使用了相同的引用,只是修改了offset和count,以此来肯定新的String对象的值。当原始字符串还在用的时候这种状况是没有问题的,而且共用value还节省了部分的空间,可是一旦原始字符串被回收,value中多余的部分就形成了空间浪费。
3.浅堆和深堆
浅堆:是指一个对象自己所消耗的内存,不包括其内部引用的对象的大小。
深堆:是指对象的保留集中全部对象浅堆的大小之和。
保留集:是指当对象A被垃圾回收后,能够释放的全部对象的集合(包括A自己),通俗的讲就是,仅被对象A所持有的对象的集合。
4.OQL查询语句
相似于sql语法的查询语句,能够在堆中进行对象的查找和筛选。
......