1、JVM启动流程
Java XXX,执行java命令后
装置配置,根据当前路径和系统版本寻找jvm.cfg文件
根据配置文件寻找JVM.dll,JVM.dll为JVM主要实现
初始化JVM,获得相关native接口,其中JNIEnv接口,该接口为JVM接口,findClass等操作通过它实现
找到main方法并运行
2、堆,栈,方法区
堆:主要保存成员变量,对象,常量池(JDK7开始,之前放在方法区),所有线程共享堆,堆是分代的
栈:保存对象的引用,一个方法内的局部变量,常量池指针,线程私有,由一系列帧组成,每一次方法调用创建一个帧,并压栈
方法区:保存Class对象的元数据(字段,方法信息,方法字节码)
Java没有寄存器,所有参数传递使用操作数栈
栈上分配:小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上,直接分配在栈上,可以自动回收,减轻GC压力,大对象或者逃逸对象无法栈上分配。
3、主内存,线程工作内存
主内存:所有线程共享的内存
线程工作内存:当前线程独享的内存,其它线程不可见
当数据从主内存复制到工作存储时,必须出现两个动作:第一、由主内存执行的读(read)操作;第二、由工作内存执行的相应的load操作;当数据从工作内存拷贝到主内存时,也出现两个操作:第一个、由工作内存执行的存储(store)操作;第二、由主内存执行的相应的写(write)操作。
每一个操作都是原子的,即执行期间不会被中断
对于普通变量,一个线程中更新的值,不能马上反应在其他变量中
4、volatile,synchronized,final
volatile:被volatile声明的变量,当一个线程修改了该变量,其他线程可以立即知道。当一个线程正在工作,需要用到另外一个线程修改某个变量后的值,对该变量用volatile声明对好。
synchronized:被它声明的方法,代码块,对象,会加上锁,在将方法执行完,代码块执行完,对象中变量值写回主内存之前,其它线程访问这些信息处于等待状态,只有真正执行完,变量值写回主内存后,才会释放锁。加锁和释放锁比较消耗性能。
final:被final声明的变量是不可变的,被final声明的对象,引用不可变,一旦初始化完成,其它线程就可见。
5、指令重排的基本原则
程序顺序原则:一个线程内包装语义的串行性
volatile规则:volatile变量的写,先发生于读
锁规则:解锁必然发生在随后的加锁前
传递性:A先于B,B先于C,那么A必然先于C
线程的start方法先于它的每一个动作
线程的所有操作先于线程的终结(Thread.join())
线程的中断(interrupt())先于被中断线程的代码
对象的构造函数执行结束先于finalize()方法
6、解释运行和编译运行
解释运行:解释运行以解释方式运行字节码,读一句执行一句
编译运行:将字节码编译成机器码,直接执行机器码,运行时编译,编译后性能有数量级的提升。
7、常用JVM配置参数
Trace跟踪参数
-verbose:gc
-XX:printGC 打印gc工作的简单信息
-XX:+PrintGCDetails 打印gc工作的详细信息
-XX:+PrintGCTimeStamps 打印gc工作发生的时间戳
-Xloggc:log/gc.log 指定GC log的位置,以文件输出
-XX:+PrintHeapAtGC 每一次GC后,都打印堆信息
-XX:+TraceClassLoading 监控类的加载
堆的分配参数
-Xmx -Xmx 指定最大堆和最小堆
Runtime.getRuntime().maxMemory()得到可用最大的内存
Runtime.getRuntime().freeMemory得到空闲的内存
java运行尽量在最小堆内存中 ,如果空间不够就会向上去取,如果达到最大上限就会报OOM错误
-Xmn 设置新生代大小
-XX:NewRatio
新生代(eden+2*s)和老年代(不包含永久区)的比值
4表示新生代:老年代=1:4,即年轻代占堆的1/5
-XX:SurvivorRatio
设置两个Survivor区和eden的比
8表示两个Survivor:eden=2:8,即一个Survivor占年轻代的1/10
-XX:+HeapDumpOnOutOfMemoryError OOM时导出堆到文件
-XX:+HeapDumpPath 导出OOM的路径
-XX:OnOutOfMemoryError 在OOM时,执行一个脚本 ,-XX:OnOutOfMemorryError=脚本的位置 %p(%p指的是当前线程),当程序OOM时,就会执行这个脚本,将当前线程的信息传送过去,也可以在OOM时,发送邮件通知,或者重启程序。
总结:
1、根据实际情况调整新生代和幸存代的大小
2、官方推荐新生代占堆的3/8
3、幸存代占新生代的1/10
4、在OOM时,记得Dump出堆,确保可以排查现场问题
永久区分配参数
-XX:PermSize -XX:MaxPermSize 设置永久区的初始空间和最大空间,表示一个系统可以容纳多少个类型
永久区的内存不够,也会导致OOM
栈的分配参数
-Xss 通常只有几百K(一般比较小,如果调大,可容纳的线程数量就会变小),决定了函数调用的深度,每个线程都有独立的栈空间,局部变量、参数、分配在栈上。
谈谈对JVM的理解(二)
猜你喜欢
转载自blog.csdn.net/qq_38019655/article/details/82670224
今日推荐
周排行