jvm基本原理

1.Jvm内存模型结构

 2.堆

堆是java虚拟机启动的时候建立的,堆中几乎存放了所有Java实例对象的信息,堆空间是所有线程共享的区域,这是与Java内存密切相关的区域。

堆中分为老年代(old)和新生代(young),其中新生代包括 Eden,S0(from),S1(to),S0和S1是两块相等的区域,刚创建的对象会先进入到新生代的Eden区,在进行一次新生代回收(minor GC)后,存活下来的对象会进入到S0或者S1中,每经过一次minor GC该对象的年龄就会+1,当该对象到达一定年龄后就会进入老年代,如图展示堆的结构

3.方法区

和堆一样是线程共享的一块区域,它用于保存系统的类信息,类的字段,类的方法,常量池等,方法区的大小决定了可以保存多少类,如果系统定义了太多的类,导致方法区溢出,同样系统也会抛出内存溢出的错误,在JDK1.6,JDK1.7中方法区可以理解为永久区(perm),在JDK1.8之后改为元数据区,元数据区和永久区不同,元数据区使用的是堆外的直接内存,如果不指定元数据区的大小(-XX:+MaxMetaspaceSize),它会耗尽系统的内存.如果元数据区溢出同样会发生内存溢出错误。

4.直接内存

Java的NIO(New IO)库处于堆外,用的是直接内存,不受Xmx大小的限制,通常访问直接内存会比java堆快,处于性能考虑,读写频繁的场合使用直接内存会优于Java堆,虽然直接内存不受Java堆大小的限制,但是堆和直接内存都受限于系统内存的最大大小

5.垃圾回收系统

垃圾回收系统可以对直接内存,方法区和堆进行回收,其中堆是垃圾回收系统的主要工作重点,标识并释放出无用的对象

6.栈

每个虚拟机都有一个私有的栈,一个线程的Java栈在线程创建的时候被创建,java栈和数据结构中的栈有着类似的含义,Java栈只包含两种操作(入栈和出栈),Java栈中保存着栈帧,还有局部变量方法参数,其中和方法的返回调用密切相关。栈帧中包含有局部变量表,操作数栈,帧数据区。

 局部变量表

        局部变量表中包含有很多的槽位,槽位之间是可以复用

操作数栈

  操作数栈保存着计算过程的中间结果,同时作为计算过程中临时变量的储存空间,操作数栈也是一个先进后出的数据结构,只支持出栈和进栈两种操作。例如自增的指令,在操作数栈中会创建两个整数并行加法计算,计算结果会被入栈。

帧数据区

帧数据区用来支持常量池的解析,正常方法返回和异常处理,在帧数据区中保存着用来访问常量池的指针,方便程序访问常量池

7.本地方法栈

本地方法栈与栈类似,最大的不同是Java栈用与Java方法,本地方法栈用于本地方法的调用(一般用C编写

8.程序计数器(PC寄存器,program counter)

PC寄存器也是每个线程私有的,Java虚拟机会为每个线程创建一个PC寄存器,,在任意时刻,Java线程总是在执行一个方法,这个方法是当前方法,PC寄存器会指向这个正在执行的方法,如果这个方法是本地方法,PC寄存器的值则为undefined

9.执行引擎

执行引擎是Java虚拟机的核心组件之一,它负责执行虚拟机的字节码。也就是将虚拟机中的方法编译成机器码后再执行

10.通过示例来描述堆,方法区,栈之间的关系

public class SimpleHeap {
    private int num;
    public SimpleHeap(int num){
        this.num = num;
    }
#方法
    public void show(){
        System.out.println("num"+num);
    }

    public static void main(String[] args) {
        #s1是(局部变量),new SimpleHeap(1)是创建一个实例对象
        SimpleHeap s1 = new SimpleHeap(1);
        SimpleHeap s2 = new SimpleHeap(2);
        #调用函数show()
        s1.show();
        s2.show();
    }
}

此声明了一个SimpleHeap类,main函数中创建了两个实例对象(new SimpleHeap(1) ,new SimpleHeap(2) )和两个局部变量(s1,s2)及其方法的引用,首先我们会在堆中创建两个实例对象,在栈中创建两个局部变量,并且两个局部变量的地址指向堆中的两个实例对象,方法区中则存在类和其方法实现(show方法),如图

11,常用的jvm参数设置

内存参数描述
-Xmx堆的最大内存大小
-Xms堆的初始化内存大小
-Xmn新生代的大小
-Xss虚拟机栈的大小
-XX:SurvivorRatio=2新生代中eden和from/to空间比例的关系含义-XX:SurvivorRatio=eden/from=eden/to=2
-XX:NewRatio=2老年代/新生代=2
-XX:+HeapDumpOnOutOfMemoryError在内存溢出时可以导出整个堆信息
-XX:+HeapDumpPath导出堆信息的文件路径
-XX:PermSizeJDK1.7之前用永久区的大小
-XX:MaxMetaspaceSizeJDK1.8之后用元数据区的大小
-XX:MaxDirectMemorySize直接内存大小,若不设置,默认为Xmx(堆最大内存)大小,
-XX:MaxTenuringThreshold该参数是新生代经过15次回收后仍然存在的对象,必然会晋升到老年代,默认为15。未达到该次数的对象也有可能会晋升
打印参数描述
-XX:+PrintGC打印GC的信息
-XX:+PrintGCDetails打印GC的详细信息
-XX:+PrintHeapAtGC打印GC对堆的详细信息
-XX:+PrintGCTimeStamps打印GC的同时输出GC的时间参数
-XX:+PrintGCApplicationConcurrentTime  打印应用程序的执行时间
-XX:+PrintGCApplicationStopedTime打印应用程序由于GC而产生的停顿时间
-XX:+PrintReferenceGC跟踪软引用、弱引用、虚引用、和Finalize队列
-Xloggc:log/gc.log不在控制台中输出GC日志,在log文件下的gc.log记录GC的日志信息
-XX:+TraceClassLoading跟踪类的加载
-XX:+TraceClassUnloading跟踪类的卸载
-XX:+PrintClassHistogram查看系统中类的分布情况
-XX:+PrintVMOptions打印虚拟机中的显式参数
-XX:+PrintCommandLineFlags打印虚拟机中的显式和隐式参数,隐式参数未必是通过命令行给出,它可能由虚拟机启动时自行设置的
-XX:+PrintFlagsFinal

打印出系统的所有参数,需要学习的可以参考参数学习

大概500多行

jvm运行模式的参数描述
-Client客户端运行(启动快,对于登录系统比较使用)
-Server服务端运行(对系统参数做优化启动,启动慢,服务运行快,对于长期运行的系统用server启动会对系统整体性能上有不小的帮助)
垃圾回收器参数描述算法
-XX:+UseSerialGC串行回收器,-Client模式下默认使用垃圾回收器在老年代用的是标记压缩算法
-XX:+UseParNewGC(多线程,独占式)

ParNew为并行回收器,启用多个线程(-XX:+ParallelGCThreads指定工作线程数)进行垃圾回收,新生代使用ParNew回收器,老年代使用串行回收器

复制算法
-XX:+UseParallelGC(多线程,独占式)新生代使用ParallelGC回收器(和ParNewGC回收器差不多,但是Parallel能控制系统的吞吐量,主要用两个参数控制-XX:MaxGCPauseMillis和-XX:GCTimeRatio),老年代使用串行回收器复制算法
-XX:+UseConcMarkSweepGC(多线程)新生代使用ParNew回收器,老年代使用CMS回收器(CMS主要关注于停顿时间STW),CMS默认启动的线程数(ParallelGCThreads+3)/4.标记压缩算法
-XX:+UseParaelOldGC(多线程,独占式)新生代使用ParallelGC回收器,老年代使用ParallelOldGC回收器,和ParallelGC功能一样,只是用来设置老年的的回收器标记压缩算法
-XX:+UseG1GC(多线程)打开G1回收器(和CMS类似,不同的是,CMS需要隔段时间进行内存碎片整理,对系统停顿时间有影响)分区算法
-XX:+ParallelGCThreads指定ParNew回收器的工作线程数,最好和CPU数量相当,默认情况下,当Cpu的数量小于8时,ParallelGCThreads的值等于CPU的数量,当CPU的数量大于8是,ParallelGCThreads的值等于3+(5*CPU_Count)/8
-XX:MaxGCPauseMillis设置最大垃圾收集停顿时间,是一个大于0的整数,ParallelGC在工作时,会调整JAVA堆大小或者其他一些参数,会尽可能的将停顿时间控制MaxGCPauseMillis内

-XX:GCTimeRatio

设置吞吐量大小,它的值是0到100之间的整数,例如,GCTimeRatio的值等于19(默认值),则系统用于垃圾回收的时间不超过1/(1+19)=5%,默认情况下,它的取值是99,即不超过1/(1+99)=1%的时间用于垃圾回收
-XX:+UseAdaptiveSizePolicyParNewGC和ParallelGC的另一个不同之处,就是ParallelGC可以使用-XX:+UseAdaptiveSizePolicy打开自适应GC策略,在手工调优比较困难的场合,可以使用该参数,仅需指定虚拟机的最大堆(Xmx),停顿时间(MaxGCPauseMillis),目标吞吐量(GCTimeRatio),让虚拟机自己完成调优工作
-XX:+CMSPreclearningEnabledCMS回收器中是否进行预清理操作,再正式清理前做准备,及控制一次停顿时间
-XX:CMSInitiatingOccupancyFraction

回收阙值,默认是68,即当老年代的使用率达到68%时就会进行CMS回收。因为CMS不是独占式的,即应用程序在不停的工作,在不断的产生垃圾,所以在CMS回收过程中还应保证系统有足够的内存空间存放新生的垃圾。在CMS过程中,已经出现了内存不足的情况,CMS就会回收失败,虚拟机将启动老年代串行回收器

-XX:+UseCMSCompactAtFullCollection开关,使CMS在垃圾回收完后进行一次内存碎片整理
-XX:CMSFullGCsBeforeCompaction设定进行多少次CMS回收后进行一次内存碎片压缩整理
-XX:+CMSClassUnloadingEnabled开关,回收perm区中的class数据
注意并发是指回收器和应用程序线程交替执行。并行是指应用程序停止,同时由多个线程一起执行GC,因此并行回收器不是并发的,并行它需要应用程序完全挂起,不存在交替执行的步骤.
-XX:+DisableExplicitGC禁用手动GC(System.gc()函数无效)
-XX:+ExplicitGCInvokesConcurrentSystem.gc()函数会使用默认的回收器,使G1和CMS回收器使用失效,该参数的作用是在使用System.gc()函数时让G1和CMS回收器能够正常使用
-XX:-ScavengeBeforeFullGC每一个并行回收器,在进行FullGC前会触发一次新生代GC,该参数是是否要出发这一次新生代GC,默认为True

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值