JVM 虚拟机

1、JAVA虚拟机概念

虚拟机,就是一台虚拟的计算机。是一款软件,用来执行一系列虚拟计算机指令。虚拟机可以分为系统虚拟机和程序虚拟机。如VisualBox、VMware就属于系统虚拟机。它们完全是对物理计算机的仿真。提供了一个可以运行完整操作系统的软件平台。程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令我们称为Java字节码指令。

2、JAVA 如何做到跨平台

同一个JAVA程序,通过JAVA虚拟机(JVM)运行于各大主流操作系统平台比如Windows、CentOS、Ubuntu等。程序以虚拟机为中介,来实现跨平台.

Linux Tomcat / JDK ——(JVM 虚拟机)详解_Linux系统

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安全优化
Linux Tomcat / JDK ——(JVM 虚拟机)详解_Linux教程_02

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");