jvm 内存简介,常见内存异常介绍

1.JVM内存区分为程序计数器、虚拟机栈、本地方法栈、方法区、堆。
程序计数器用来记录命令执行的行数,每个线程都有一个计数器记录当前运行行,基本不占内存。
虚拟机栈和本地方法栈在HotSpot中是一块区域,用来存储基本的8种对象和对象的引用。(-Xss128k 栈的容量为128k,递归2000余次会因为栈深度过大而抛出StackOverflowError)
方法区用来存储加载的类信息、常量、静态变量、即时编译的代码,HotSpot中叫永久代。其中的一部分叫做运行时常量池,用来存储编译期生产的各种字面量和符号应用。(-XX:PermSize=10m -XX:MaxPermSize=10m 设置方法区10m不能扩展,当加载的类过多或者生成的代理过多时,会产生PermGen space 异常)
堆就是对象的存储区域,所有对象和数组都要在堆上分配内存。(-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 堆最小20m,最大20m,不能自动扩展,堆溢出--Java heap space 异常--要输出dump)
2.JVM内存回收方式
不是引用计数算法,是根搜索算法,会检测对象是否和GC Root对象们有关联,有就不回收,没有就回收。
回收不是直接回收,如果第一次发现没有和GC Root对象们有关联,会标记一下,如果下次回收时已经有前科,立即回收。期间对象的finalize()方法仅仅会被执行一次,而且不保证肯定会被执行,不要依赖它进行任何操作。
具体操作时:
新生代:JVM会将可以使用的内存划分为几块,在其中一块上保存对象,当需要回收时,将活着的对象移到另一块新区域,然后将整个区域回收。
老年代:将活着的对象定期移动到区域的一端,需要清理时,将活动区域边界以外部分回收。
3.JVM收集器介绍
Serial:单线程中断式收集器,最古老,在单核CPU且允许毫秒级中断的应用上效率最好
ParNew:Serial的多线程版本,Server模式下新生代收集器首选,能和CMS收集器搭配(使用-XX:+UseParNewGC 强制JVM使用ParNew;使用-XX:+UseConcMarkSweepGC 默认启用;可以用-XX;ParallelGCThreads指定GC线程数目)
Parallel Scavenge: 关注于吞吐量(吞吐量优先收集器),和ParNew类似,但是可以设置吞吐量(程序运行100分钟,GC时间1分钟,吞吐量99%)。参数为 -XX:GCTimeRatio 和 -XX:MaxGCPauseMillis。MaxGCPauseMillis表示停顿进行垃圾回收的时间,时间越短收集的次数越多;GCTimeRatio 是总时间比例,设置为19表示垃圾回收时间占用(1/(1+19))5%,默认为99即(1/(1+99))1%。不能和CMS配合。
Serial Old 、Parallel Old: 两者的老年代收集器版本。
Concurrent Mark Sweep: 以获得最短停顿时间为目标的收集器。适合Server端应用(重视响应速度,希望回收停顿时间尽可能短)。默认启用(cpu数量+3)/4 个线程,在4核cpu以上的系统表现很好。但是可能产生“Concurrent Mode Failure”,从而导致一次Ful GC。如果在应用中老年代增长不快,可以适当调整-XX:CMSinitiatingOccupancyFraction的值来增大默认68%的CMS对老年代的回收阀值。但是太高反而会导致CMS出现“Concurrent Mode Failure”,JVM会启用备用的Serial Old来收集老年代,时间反而会更久。还可以设置-XX:+UseCMSCompactAtFullCollection,当每次Full GC后进行一次内存整理,配合-XX;CMSFullGCsBeforeCompaction来计数多少Full GC出发一次内存整理。
G1:相比CMS,G1采用标记整理算法,不会和CMS采用标记清楚算法一样参数内存碎片。同时G1将新生代、老年代划分为更加细致的固定区域,分别进行垃圾回收,避免全区域垃圾回收。维护一个区域优先级列表,每次回收最容易产生垃圾的区域。G1是目前最高效的收集器。
4.JVM内存分配
新生对象在Eden区域分配,Eden区域没有空间时,产生一次Minor GC。(-XX:+PrintGCDetails 用来收集GC日志 -XX:SurvivorRatio=8 Eden区和Survivor区域比是8比1)。
Minor GC相比Full GC非常频繁发生,是指在新生代进行垃圾回收。Major GC/Full GC 是对老年代的垃圾回收,比Minor GC慢十倍以上。通常一次Major GC会伴随一次以上Minor GC。(-Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8 堆起始、最大20m,不能拓展,10m分配给新生代)。
大对象一般会直接进入老年代,所有写程序应该尽可能避免大量的“短生命的大对象”(大字符串、数组等等),这样会频繁触发GC。虚拟机可以使用-XX:PretenureSizeThreshold参数(只对Serial ParNew有效)来配置大于此阀值的对象直接进入老年代。
当一个对象在Eden区域GC后仍然存活,就会被Survivor区域接受,同时设置Age为1,当他的Age逐步增长到15(默认值)时,会被老年代接受。即长期存活对象晋身老年代。年龄阀值可以用-XX:MaxTenuringThreshold设置。当Survivor区域中的大部分对象都是平均年龄,当空间不足时,大于平均年龄的对象可以直接晋身老年代。
当Survivor空间不足,Eden中的对象可能直接进入老年代,如果老年代判断剩余空间不足,直接FULLGC。当判断空间满足时,当 -XX:HandlePromotionFailure 为true时,进行Minor GC,同时将新生代转移到老年代;如果为false,会进行FULL GC。如果老年代判断失误导致新生代进入老年代而出现handel promotion failure,会进行一次FULL GC。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值