翻看电脑的文件夹,无心看到了9月份在公司作的一次分享,浏览了一下"婆婆特",发现本身在ppt上的写的引导性问题本身也不能确切的回答出来,哎,知识这东西,平时不经常使用的没些日子就生疏了。因而,本小白决定把他整理下来,不敢班门弄斧,对于入门的同窗能够快速了解虚拟机的大概,有错误的地方请批评指正。html
1、java虚拟机的内存结构java
public class ReferenceCountGc {程序员
public Object field = null;算法
public static void main(String[] args) {windows
ReferenceCountGc objA = new ReferenceCountGc();数组
ReferenceCountGc objB = new ReferenceCountGc();安全
objA.field = objB;多线程
objB.field = objA; app
objA = null;性能
objB = null;
System.gc();
}
}
当程序执行到System.gc()时,是否会回收对象objA和objB?
引用计数方法:给对象一个计数器,当对象被引用时就+1,释放掉引用-1,当为0时及不会再被引用。但引用计数方法的Bug是没法解决对象循环引用的问题,但并非此算法没有用武之地,在不少场景下会使用到这个算法。但java的垃圾回收并无使用。上面的程序若是使用的是引用计数算法则不会被回收,但虚拟机却使用根搜索算法。
根搜索算法即设定一个对象称为GC root ,从这个节点向下进行搜索,搜索所走过的路径称为引用链,当GC root没有任何引用链相连即在图论中不可到达,则证实此对象不可用
由此来看看,对象死后,垃圾回收算法;
标记-清除算法 复制算法
灰色矩形框为可回收对象,标记-清除算法就是把可回收的对象进行标记,标记到必定次数则清除掉。从图中能够明显看出,该算法的弊端是会产生大量的磁盘碎片,没有一整片连续的空间,当遇到占用连续的内存空间较多的对象时,因为内存放不下该对象,会提早进行垃圾回收,导致虚拟机垃圾回收频繁,影响性能
为了规避标记清除算法的弊端,出现了复制算法,复制算法将内存一份为二,垃圾回收时将使用的内存中的存活对象,拷贝到另外一半内存中,而后把左侧内存区域彻底清除掉,上图只是演示了复制算法,但并不是一分为二,使用和保留的空间是1:1,能够根据实际状况对虚拟机参数进行调整。此算法的弊端是要保留内存空间,会将可用内存变少。
标记整理算法: 分代收集算法:
标记整理算法:绿色和蓝色区域都表明存活对象,当进行垃圾回收时把存活对象依次移到最左边,移动后将其他内存空间清空。
分代收集算法:如图,其实就是没有算法。。。把以上3种算法进行综合运用,前面说过堆是有划分的,简单分为新生代和老年代,分代收集就是根据不一样代的特色应用不一样的垃圾回收算法。
3、java内存分配
java的自动内存管理解决了两个问题,一是给对象分配内存,二是回收分配给对象的内存,前面咱们讲了回收分配给对象的内存,下面咱们来看看给对象分配内存
java堆分为新生代,老年代(终身代)和永久代。
新生代和老年代的默认比值为1:2即新生代占堆总内存的1/3,能够经过 –Xms(初始堆大小)、-Xmx (最大堆大小)来改变。
新生代又分为Eden区、From survivor区、To survivor区,Eden:From:To 为 8:1:1,能够经过–XX:SurvivorRatio 参数设定。
JVM每次只会使用From区和survivor区中的一块(Form survivor或To survivor),很明显是为了在垃圾回收的时候将存活对象移到另一个空闲的survivor区(若是空间足够,不然直接进入老年代),所以垃圾回收所使用的算法是复制算法。
新生的对象会被分配到新生代,新生代的特色是朝生夕死,对象存活的时间短,迭代快。发生在新生代的垃圾回收叫minor GC,minor Gc进行的相对频繁,消耗较full GC少,而Full GC是发生在老年代的垃圾回收,采用的是标记-清除算法。老年代进行一次垃圾回收比新生代话费时间长,进行的也没有老年代频繁,同时要尽可能减小老年代的垃圾回收,由于回收速度慢且在进行时影响虚拟机性能,使虚拟机响应变慢,最直接的感受是应用程序的响应速度变慢。
什么状况下,对象会被分配到老年代?
从上图中明显能够到3点:
大对象:什么是大对象,大对象就是须要连续占用不少内存空间的对象好比很长的字符串和数组。虚拟机经过-XX:PretrnureSizeThreshold设计大过指定大小的对象之间进入老年代,即时没有超过指定大小,在进行minor GC时一般也会由于survivor区不够用而被转移到老年代。
经过设置MaxTenuringThreshold参数: 这个参数是进行年龄设置的,超过这个年龄的会进入老年代。什么是年龄?在新生代进行minor GC的时候,每进行一次,存活下来的对象年龄+1,默认年龄超过15的会进入老年代。15这个数值也能够经过MaxTenuringThreshold参数改变。
Survivor空间中相同年龄全部对象大小的总和大于survivor空间的一半,全部大于或者等于该年龄的对象直接进入老年代,这句话比较拗口,但就是这个意思,看不懂的多看几遍就行了。。。
前面讲了这么多参数,如何设置虚拟机参数?能够经过IDE进行设置,不管是调整空间大小,仍是设置对象的年龄进入老年代,以下图
3、咱们开发中应注意的问题
从虚拟机上能够看出,主要是避免full GC的次数,减小朝生夕死的大对象,对虚拟机内存进行优化,在平常开发中写程序的主要注意的是
不要使用长字符串 如:String x = new String(“XXXXXXXXXXXX”) StringBuffer stringBuffer = new StringBuffer()StringBuffer对象的append()方法。固然,考虑到线程安全问题,使用StringBuilder.