老生常谈,面试吹牛的的最佳谈资,在接下来的几天里,我找了点资料来对其进行一波学习;html
本地环境是不须要对咱们的虚拟机进行优化的,通常在生产环境下,也就是Linux下才有对JVM优化的需求java
在JVM中有不少的参数是能够设置的,这些参数咱们把它分为三类面试
标准参数(比较稳定的,在将来的版本更迭中,都不会丢失的,非标准的参数不能保证)sql
-X参数(也就是非标准的 java -X 查看全部的参数)数组
-XX参数(也是非标准参数,这种类型的参数通常都是用于JVM的调优改动)tomcat
java -help:查看命令,咱们能够在里面找到上面所说的三种类型的的影子jvm
java -version :查看jvm的版本工具
java -showversion :查看kvm版本信息,并执行其后的其余命令(经常使用)学习
-D:设置系统参数,至关于上下文,咱们能够添加K和V进去,而后拿到K的值测试
首先咱们去Linux上写一个测试类以下所示:
而后咱们去编译并运行它:
可见是没有值的,下面咱们就对“chen”这个K,设置Value,让他被获取到:
![]()
java -Dchen=HelloWorld test1:意思为设置系统属性”chen“,为其赋值为HelloWorld,而后再运行test1文件,
最后输出结果已经能够发现,系统属性设置生效
-server 和 -client 模式
server模式的话,jvm的初始化堆空间会大一些,启动慢,可是后续的运行就很是的丝滑
client模式的话,jvm初始化的堆空间就会小一点,启动很是快,可是运行相对较卡
这个都是了解部分,觉得jvm在启动的时候会根据硬件和系统自动给我选择最合适的模式
如今的机器基本都是64位的系统吧,64位的系统只支持server模型,只要机器给力都是选择server模式
咱们能够经过java -X 这个命令去获取全部-x的参数列表
-Xms和-Xmx参数设置堆内存的初始化大小和最大大小
-Xmx2048m:表示设置JVM的最大堆内存为2048兆
-Xms512m:表示设置JVM的初始化堆内存为512兆
-Xint、-Xcomp、-Xmixed,这三个参数的配置
-Xint,解释模式,会强制jvm逐行执行全部的字节码,运行速度很明显的变慢
-Xcomp,编译模式,jvm在第一次使用时会把全部的字节码编译成本地代码(会卡一下),带来最大的优化效果
-Xmixed,混合模式,将解释模式与编译模式进行混合使用,由jvm本身决定,默认使用该模式
编译模式下会卡顿一下再弹出结果,这个值得注意一下,但这也是一种优化,后面执行就会很是流畅
上面已经说到,-XX也是非标准参数,主要用于jvm的调优和debug的操做
-XX参数的使用分为两种方式,一种boolean类型,一种非boolean类型
boolean类型
-XX[+/-]<name> :表示启动或者禁用某个属性,+:启动,-:禁用
如:-XX:+DisableExplicitGC:表示开启禁用手动调用gc操做,也就是说System.gc无效
非boolean类型
-XX:<name>=<value> :表示name的值为Value
如:-XX:NewRatio=1 :表示新生代和老年代的比值
运行Java命令时打印出运行参数
执行:java -XX:+PrintFlagsFinal test1
会获得一堆信息配置的信息,大部分的信息咱们都看不懂,但仍是有一点须要说明
在咱们获得的信息列表中都是KV结构的,V通常分为true/false或者为属性值这两种方式
k=V,这种经过=符号表示的,是使用的默认值
k:=V,这种方式表示已经被咱们改动,是使用的咱们给定的参数
查看正在运行的java进程的参数
启动一个tomcatu用于测试,下面咱们经过jinfo命令查看全部的运行参数信息
jinfo -flags <进程id>:进程ID,咱们能够经过ps -ef | grep tomcat 拿到,下面咱们一块儿来看看
经过上面这张体,能够发现,不少参数被被打印了,虽然咱们大部分都不知道他的意思,但咱们仔细读读仍是有那么两个咱们在上面讲过的
若是咱们只想单一的查看某个运行参数的值,咱们能够经过下面这种方式获取:
jinfo -flag <参数名称> <进程id>,好比咱们去获取最大的堆内存空间大小:
你也能够 :回顾往日学习:jvm内存模型
首先咱们须要知道的是,了解JVM的内存模型对于JVM调优有什么帮助?
[JDK1.7] :年轻带——老年代——永久代 (统一被JVM虚拟机管理)
[JDK1.8]: 年轻带——老年代——元空间(元空间被操做系统本地内存内管理)
整体上划分为了三个板块,每一个板块中都会再进行细度划分,但都有一个伸缩区的存在,且占有大量内存空间
咱们在JVM内存模型中的优化主要就是针对这个伸缩区的大小进行根据项目进行调整,实现优化效果
jdk1.8的内存模型:
【年轻代】:被细分为三个区域[Eden区、两个大小严格相同的Survivor区、伸缩区]
Eden区用于存放刚刚建立的对象,空间占满了就会触发GC,有些对象在GC后仍然保留了下来,进入存活区
存活取有两个严格相同大小的空间,某一时刻,只有一个是在被使用的,好比图中的S0用来存放Eden过来的对象
当S0空间不足,触发GC时,就会把仍然存活的对象复制到S1,而后把S0的内存空间给刷掉
根据JVM的策略,再存活取通过几回GC后,而后存在的对象就会被存放到老年代中去
【老年代】:被细分为 [旧生代、伸缩区]
主要保存生命周期较长的对象,用于分撒年轻的储存压力
当我建立的是一个比较大的对象时,会跳过年轻带直接进入老年代储存
【元空间】:替换了1.7中的永久代,被细分为[CCS、CodeCache]
CodeCache:存放类,class等数据
CCS:类的压缩指针,默认不开启,不作使用
【伸缩区 Virtual区】:最大内存和初始内存的差值,就是伸缩区,这就是咱们优化的目标所在
为何废除1.7的永久代和使用寄存在本地内存中的元空间
由于永久代内存常常不够用且有发生内存泄漏的隐患,爆出内存空间不足的错误
基于此,将永久代废弃,采用基于本地内存空间的元空间
jstat:能够查看堆内存中各部分的使用量,以及加载类的数量
格式:jstat -命令现象 进程id 运用以下所示
Loaded:Tomcat启动一共加载的class数量
Bytes:所占用的空间大小
Unloaded:未加载数量
Bytes:未加载占用空间大小
Time:加载所耗时间
Compiled:编译数量
Failed:失败数量
Invalid:不可用数量
Time:编译所耗时间
FailedType:失败类型
FailedMethod:失败的方法
咱们能够经过使用 jstat -gc 2310 1000 5
这种命令来屡次查看,好比上面这个命令的意思为:一秒执行一次,一共执行五次
眼睛都给我看瞎了,卧槽!
soc:第一个 Survivor区的大小
s1c:第二个 Survivor区的大小(严格规定大小一致)
s0u:第一个 Survivor区的使用大小
s1u:第二个 Survivor区的使用大小
EC:Eden区的大小(KB)
OC:Old区大小(KB)
OU:Old使用大小
MC:方法区大小(KB)
MU:方法区使用大小
CCSC:压缩类空间大小(KB)
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
jmap相比jstat能够获取到更多详细的数据
jmap -heap 进程id,以下所示
jmap -histo 2310 | more :查看全部对象,包括活跃以及非活跃对象的相关信息
jmap-histo:live 2310 | more :查看活跃的对象详细
其余你不认识,String总该认识吧。经过上面的命令,咱们知道String在Tomcat这个进程中一共建立了31768个对象,占用内存762432K大小,至于其余的让咱们慢慢写来
B :byte
C:char
D:double
F:float
I: int
J: long
Z: boolean
[ :数组,能够上面配合使用
[L + 类名 :其余对象
可见,byte数组建立的UI底下那个不是最多的,可是所占用的内存开销确是最大的
什么意思呢?dump:转储
也就是将咱们的内存的使用状况输出到文件中,而后咱们对其进行分析
jmap -dump:format=b,file=指定转储文件绝对路径 进程id
上面咱们已经经过dump命令,将咱们的Tomcat的 内存使用状况转储到了本地dump.dat文件中
下面咱们经过jhat对该文件进行分析,jhat用法以下:jhat -port 自定义端口号 dump文件绝对路径
上面能够看到,我本地已经对其进行了访问,每一个对象都是以包的方式集结在一块儿,因此若是想要看咱们本身写的代码的话,去找包就能找到,点击进去我发现个人功力还不够,看不出什么名堂来,
下面讲另外一个东西,咱们直接网页翻到最底部:最后一行数据:[Execute Object Query Language (OQL) query]
OQL:这是一种检索语言,有点像sql,咱们点进去,查看相关的帮助文档:
测试一把,咱们调整检索条件? 把字符长度调整到1W去,再次检索
能够发现,不少都是配置文件,Tomcat内部将配置文件读取后赋值给了一个String对象