Java程序的执行过程:
Java源代码文件(.java)会被Java编译器编译为字节码文件(.class),然后由JVM中的类加载各个类的字节码文件,加载完毕后,交由JVM执行引擎执行。整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要的数据和相关信息,这段空间一般被称作Runtime Data Area(运行时数据区)也就是JVM内存。因此,在JVM中常常说到的内存管理就是针对这段空间管理(如何分配和回收内存空间)
方法区:被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,包含运行时常量池,编译的代码等数据,包含运行时常量池,编译期生成的各种字面量和符号引用,在类加载后存放到方法去的运行时常量池中。运行期间也可能将新的常量放入池中比如String类的intern()方法,线程共享区域;
堆:唯一目的,存放对象实例,GC主要管理区域,是JVM最大一块区域;在虚拟机启动时创建,几乎所有对象实例都在这里分配内存,线程共享区域;
虚拟机栈:存储局部变量(基本数据类型,对象引用) returnAddress类型,线程私有,它的生命周期于线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧用于存储局部变量表,操作数栈,动态链表,方法出口信息等。每一个方法从调用知道执行完成的过程,就对应一个栈帧在虚拟机中入栈到出栈的过程。
本地方法栈:本地方法站属于线程私有数据区域,这部分主要于虚拟机用到的Native方法相关,一般情况下,无需关心
程序计数器:字节码解释器工作时,通过改变整个计数器的值来选取下一条需要执行的字节码指令的地址,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖整个计数器来完成,多线程中,为了让线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。各条线程之间互不影响,独立存储,因此这块内存是线程私有的。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-XX 参数,也是非标准参数,主要用于JVM的调优和debug操作 ①boolean类型 格式:-XX[+-] <name> 表示启用/禁用<name>属性;如:-XX: + DisableExplicitGC禁用手动调GC也就是说调用System.gc()无效 ②非boolean类型 :=代表值被修改
-Xms 和 -Xmx 分别是设置jvm的堆内存的初始大小和最大大小
-Xms 2048m 等价于 -XX:MaxHeapSize,设置JVM最大堆内存为 2048M
-Xmx 512m 等价于 -XX:InitialHeapSize,设置初始化堆内存512M
如 Java -Xms 512m -Xmx 2048m Test
查看正在运行的jvm参数:jinfo 用法: 查看所有参数 jinfo -flags 5212 查看某个参数: jinfo -flags MaxHeapSize 5212
查看正在运行的tomcat 进程id ps -ef | tomcat
查看正在运行的Java相关进程 jps; jps -l 可查看其路径
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数] 如 jstat -class 5212. jstat -compiler 5212 jstat -gc 5212 垃圾回收统计:jstat -gc 5212 1000 10
jmap 查看内存使用情况 jmap -heap 5212 查看所有对象(包括活跃/非活跃对象)jmap -histo<pid> | more 活跃对象: jmap -histo:live 5212 | more
将内存使用情况 dump到文件中: jmap -dump:format = b.file = /tmp/dump.dat 5212
通过 jhat 对 dump文件进行分析 jhat -port<port><file> : jhat -port 0000 /tmp/dump.dat 浏览器ip + 9999 或者MAT工具
jstack Jvm线程执行情况 jstack <pid> 将正在运行的jvm线程情况进行快照打印出来 可查死锁; New Running运行态 ready就绪态 timed_waiting超时等待态 waiting等待 blocked阻塞态
visualVM工具 jdk自带可视化 内存/线程等信息
sz 文件 下载到本地 rz上传
visualVM监控远程tomcat 对外开放 JMX 启动tomcat 查日志 ./startup.sh && tail -f ../logs/catalina.out
1. 在tomcat的bin目录下,修改catalina.sh
2. 在visualJvm中添加主机IP加端口号,192.168.0.255:9999
垃圾回收常见算法:
1. 引用计数算法:运行时根据对象的计数器是否为0;无法解决循环引用问题
2. 标记清除法:root指向被标记,没有则清除;效率低,碎片化严重
3. 标记压缩法:从根节点标记对象,解决碎片化问题;移动内存位置,效率低
4. 复制算法:垃圾回收之后空间比较完整;垃圾对象多,效率高;内存使用率低,垃圾对象少的时候
5. 分代算法:根据回收对象的特点选择,在jvm中,年轻代使用复制算法,老年代使用标记清除法或者标记压缩法
垃圾收集器:
1. 串行垃圾收集器:STW 效率低,一个线程
2. 并行垃圾收集器:STW
3. CMS垃圾收集器:针对老年代,效率高
4. G1垃圾收集器:设计原则就是简化JVM性能调优,开发人员三步杰克完成调优①开启G1垃圾收集器②设置堆的最大内存③设置最大停顿时间
G1中提供三种模式垃圾回收 youngGC MixGc 和FullGC在不同条件下触发
原理:取代物理上的分区
技术亮点:RememberSet 用Rset区记录,哪个对象引用了自己,目的:跟踪指向某个堆内的对象引用
GC步骤分2步:①全局并发标记 ②拷贝存活对象
GC Easy 可视化工具 首先生成一个gc.log文件通过指令: -XX:MaxGCPauseMillis = 100 -XX:+PrintGCDetails -XMx 256m
tomcat优化:一是tomcat自身的配置 二是 tomcat所运行的jvm虚拟机的优化
1. 禁用AJP服务 2. 修改server.xml文件 配执行器(线程池)(设置吞吐量于响应时间的平衡)3. 设置NIO2 4. 调整JVM参数优化(垃圾回收用G1)
代码优化:// TODO