JVM 虚拟机
1、JAVA虚拟机概念
虚拟机,就是一台虚拟的计算机。是一款软件,用来执行一系列虚拟计算机指令。虚拟机可以分为系统虚拟机和程序虚拟机。如VisualBox、VMware就属于系统虚拟机。它们完全是对物理计算机的仿真。提供了一个可以运行完整操作系统的软件平台。程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令我们称为Java字节码指令。
2、JAVA 如何做到跨平台
同一个JAVA程序,通过JAVA虚拟机(JVM)运行于各大主流操作系统平台比如Windows、CentOS、Ubuntu等。程序以虚拟机为中介,来实现跨平台.
3、虚拟机堆内存结构
JVM中堆空间可以分成三个大区,年轻代、老年代、永久代(方法区)。
新生代:新生区类在这里产生和应用,最后被垃圾回收。所有的对象在这个区被new出来,当这个区满了,GC会对该区不用的对象销毁,剩余有用的转到幸存区。
老年代:老年区 用于存放生成周期比较长的对象。
永久代:永久区 存放JDK自带的class,interface。
jvm区域总体分heap区和非heap区。
heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。
·
非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。
4、常用虚拟机参数
JVM 虚拟机提供了三种类型参数
1)、标准参数
标准参数中包括功能和输出的参数都是很稳定的,很可能在将来的JVM版本中不会改变。你可以用 java 命令(或者是用 java -help)检索出所有标准参数。
2)、X 类型参数
非标准化的参数,在将来的版本中可能会改变。所有的这类参数都以 -X 开始。
3)、XX 类型参数
X 参数的功能是十分稳定的,所有的 XX 参数都以"-XX:“开始,但是随后的语法不同,取决于参数的类型:1)对于布尔类型的参数,我们有”+“或”-",然后才设置 JVM 选项的实际名称。 例如,-XX:+ 用于激活选项,而 -XX:- 用于注销选项。 Example: 开启GC日志的参数: -XX:+PrintGC2) 对于需要非布尔值的参数,如 string 或者 integer,我们先写参数的名称,后面加上"=",最后赋值。
4)、常用的JVM参数
(1)、配置JAVA虚拟机的堆空间
-Xms:初始堆大小
-Xmx:最大堆大小
实际生产环境中, 我们通常将初始化堆(-Xms) 和 最大堆(-Xmx) 设置为一样大。以避免程序频繁的申请堆空间。设置为物理内存的一半。
[root@java-tomcat1 bin]# vim catalina.sh 添加
JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx1024m"
(2)、开启GC日志
跟踪JAVA虚拟机的垃圾回收
GC日志:jvm垃圾回收,记录jvm的运行状态,oom内存溢出的报错信息等。
%t 将会被替代为时间字符串,格式为: YYYY-MM-DD_HH-MM-SS
开启GC日志:
[root@java-tomcat1 bin]# vim catalina.sh 添加JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx1024m -Xloggc:/data/logs/gc-%t.log"
[root@java-tomcat1 bin]# mkdir -p /data/logs
重启tomcat
8、JVM 运维实用排障工具
1)、jps
用来查看Java进程的具体状态, 包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示java进程
常用参数如下:
-v:输出传给jvm的参数
·
注意: 使用jps 时的运行账户要和JVM 虚拟机启动的账户一致。若启动JVM虚拟机是运行的账户为www,那使用jps指令时,也要使用www
用户去指定。 sudo -u www jps
例如:
#查看已经运行的JVM 进程的实际启动参数
[root@java-tomcat1 ~]# jps -v
58154 Jps -Denv.class.path=.:/usr/local/java/lib:/usr/local/java/jre/lib:/usr/local/java/lib/tools.jar -Dapplication.home=/usr/local/java -Xms8m
58015 Bootstrap -Djava.util.logging.config.file=/data/application/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/data/application/tomcat -Dcatalina.home=/data/application/tomcat -Djava.io.tmpdir=/data/application/tomcat/temp
2)、jstack
jstack用于打印出给定的java进程ID或远程调试服务的Java堆栈信息。此信息通常在运维的过程中被保存起来(保存故障现场),以供 RD (开发人员)们去分析故障。
常用参数:
jstack
jstack [-l] //长列表. 打印关于锁的附加信息
jstack [-F] //当’jstack [-l] pid’没有响应的时候强制打印栈信息
如
#打印JVM 的堆栈信息,以供问题排查
[root@mouse03 ~]# jstack -F 38360 > /tmp/jstack.log
9、Tomcat安全优化
1)、降权启动(强制)
[root@java-tomcat1 ~]# useradd tomcat
[root@java-tomcat1 ~]# chown tomcat.tomcat /usr/local/tomcat/ -R
[root@java-tomcat1 ~]# su -c '/usr/local/tomcat/bin/start.sh start' tomcat
Using CATALINA_BASE: /data/application/tomcat
Using CATALINA_HOME: /data/application/tomcat
Using CATALINA_TMPDIR: /data/application/tomcat/temp
Using JRE_HOME: /usr/local/java
Using CLASSPATH: /data/application/tomcat/bin/bootstrap.jar:/data/application/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@java-tomcat1 ~]# ps -ef | grep tomcat
tomcat 1065 1 64 20:33 ? 00:00:06 /usr/local/java/bin/java -Djava.util.logging.config.file=/data/applicationtomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /data/application/tomcat/bin/bootstrap.jar:/data/application/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/data/application/tomcat -Dcatalina.home=/data/application/tomcat -Djava.io.tmpdir=/data/application/tomcat/temp org.apache.catalina.startup.Bootstrap start
root 1112 1027 0 20:33 pts/0 00:00:00 grep --color=auto tomcat
10、Tomcat性能优化
- 上策:优化代码
需要开发经验足够丰富,对开发人员要求较高
- 中策:jvm优化机制 垃圾回收机制 把不需要的内存回收
优化jvm–优化垃圾回收策略
优化catalina.sh配置文件。在catalina.sh配置文件中添加代码
# tomcat分配1G堆内存模板
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m
# 重启服务
su -c '/home/tomcat/tomcat8_1/bin/shutdown.sh' tomcat
su -c '/home/tomcat/tomcat8_1/bin/startup.sh' tomcat
- 下策:加足够大的内存
该项的资金投入较大
- 下下策:每天0点定时重启tomcat
使用较为广泛
11 、设置 JVM 缓存
在主机名解析为 IP 地址后,资源 IP 地址将保存在 JVM 的高速缓存中。如果改变了资源的 IP 地址,则需要重新启动应用服务器,使 Identity Manager 能够检测所做更改 (ID-3635)。这是 Sun JDK(1.3 及更高版本)中的设置,可以使用 sun.net.inetaddr.ttl 属性(通常在 jre/lib/security/java.security 中设置)控制
设置解析成功的域名记录JVM中缓存的有效时间,JVM默认是永远有效,这样一来域名IP重定向必须重启JVM,这里修改为5秒钟有效,0表示禁止缓存,-1表示永远有效
java.security.Security.setProperty("networkaddress.cache.ttl", "5");
//设置解析失败的域名记录JVM中缓存的有效时间,JVM默认是10秒,0表示禁止缓存,-1表示永远有效
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "2");
还有两种方式设置dns缓存
方式一:在JAVA_OPTS里设置
-Dsun.net.inetaddr.ttl=3 -Dsun.net.inetaddr.negative.ttl=1
方式二:修改property
System.setProperty("sun.net.inetaddr.ttl", "3");
System.setProperty("sun.net.inetaddr.negative.ttl", "1");