`
bearsorry
  • 浏览: 92971 次
  • 性别: Icon_minigender_2
  • 来自: 湖南
社区版块
存档分类
最新评论

JVM垃圾回收算法

    博客分类:
  • JVM
JVM 
阅读更多

   发现自己真的好久木有写博客了呃...一直只顾着看书做笔记什么的,也该是时候练练表达能力了!废话不多说,接着上次的博客写吧,还是有关于JVM方面的东西!

 

   

    Java虚拟机其实就是虚拟机的一种,看了两遍800多页的操作系统之后,我的理解是虚拟机就像是真实的机器一样为我们提供系统或者程序提供服务,它是将硬件设备以及软件资源整合起来,为系统或者程序提供直接的调用,这样在一台机器上就可以产生几个虚拟机。虚拟机对用户是透明的,至于虚拟机与操作系统具体是一个什么关系,应该比较复杂吧,虚拟机为操作系统提供了一个运行的平台,这里就此把虚拟机划分为两类:系统虚拟机和程序虚拟机。系统虚拟机就是刚才说的那种了,然而程序虚拟机就是为程序服务的了,就像java虚拟机一样,这里应该对java虚拟机有一点概念了吧,想想我们在运行java程序的时候,一个main函数开始的程序就占用一个java虚拟机,在这个程序里面所使用的所有资源都是这个虚拟机所提供的,下面先来看看JVN是怎样工作的吧!

 

   

   Java虚拟机还是不能脱离操作系统工作的吧,所以JVM的工作就是从操作系统装载JVM开始的,操作系统是通过jdk中的java.exe来完成的,接着就是配置JVM的环境了,分成以下四步:

1、创建JVM装载环境和配置

2、装载JVM.dll

3、初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例

4、调用JNIENV实例装载并处理class类

  

   JVM在整个jdk中处于最底层的,负责操作系统的交互,用来屏蔽操作系统环境,提供一个完整的java运行环境。

   首先是将JVM装入环境,JVM提供的方式是操作系统的动态链接文件,这里就简要说一下吧,既然是装载JVM的文件,那么操作系统会在你的path下面找到你的程序的java.exe,再从里面通过各种调用寻找jvm.dll以及jvm.cfg,将其装载到操作系统,这样就可以在java中调用JVM的函数了。这些工作做完之后就开始运行java程序了,Java程序有两种方式一种是jar包,一种是class. 运行jar,Java -jar XXX.jar运行的时候,Java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用Java类           Java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用Java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。main函数直接调用Java.c中LoadClass方法装载该类。如果是执行class方法。main函数直接调用Java.c中LoadClass方法装载该类。

 

   熟悉JVM的工作原理之后,我们再接着上篇博客的JVM中垃圾回收机制的算法说说吧:

 

一、按照基本回收策略划分

引用计数:这是一种比较传统古老的方法,原理是这样的,垃圾回收不就是对木有引用的对象进行占据内存空间的释放么,这里就是给每一个对象一个计数,当对象的引用增加一个时,它的计数就增加1,当删除一个引用的时候就减1,垃圾回收的时候就只会对计数为0的对象进行空间的释放,但这种方法不能处理循环引用的问题:

例如:

public void buidDog()

{

Dog newDog = new Dog();

Tail newTail = new Tail();

newDog.tail = newTail;

newTail.dog = newDog;

}

这里如果要回收newDog的话,前提是newTail被回收,然而要回收newTail的前提是newDog被回收,这样这两个对象都不能被回收了!

 

标记—清除(Mark-sweep):此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。

 



 

 

 

复制(copying)

此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。

 



 

 

标记—整理(Mark-Compact)

此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。

<!--EndFragment-->

 

 



 

 

二、按分区对待的方式划分

增量收集:即在应用进行的时候同时进行垃圾回收

分代收集:这种方法就是根据之前我在博客中的那种根据对不同对象的分代来进行垃圾回收

三、按系统线程来划分

串行收集:使用单线程来处理垃圾的回收工作

并行收集:使用多线程来处理垃圾回收工作

以上介绍了一些基本的垃圾回收的算法,将这个写出来也是给自己加深一下印象吧,这几种算法不能绝对的说那种比那种好,这个也会根据计算机发展而进行改进的,比如说串行收集就适合单处理器机器,并行收集就适合在多处理器机器上,当然抛开其他外部条件来说,并行的收集方式还是效率高一些!

关于JVM垃圾回收调优方面的内容将在下一篇博客里面接着来讨论!

<!--EndFragment-->

 

 

<!--EndFragment--><!--EndFragment-->
  • 大小: 3.2 KB
  • 大小: 4.6 KB
  • 大小: 3.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics