浅析Java中的GC垃圾回收器的意义及与GC的交互_java

对象是使用new创建的,但是并没有与之相对应的delete操作来回收对象占用的内存。当我们完成对某个对象的使用时,只需停止对该对象的引用:将我们的引用改变为指向其他对象或指向null;或者从方法中返回,使得该方法的局部变量不复存在,从而使得对这些局部变量的引用变为不指向任何对象。不再被引用的对象被称为垃圾(garbage),查找并回收这些对象的过程叫做垃圾回收(garbage collection) o

  Java虚拟机利用垃圾回收来保证被引用的对象将会在内存中保留,同时会释放在执行代码中通过任何引用都不可达的对象所占用的存储空间。这是一种强保证—如果顺着从根引用(即在执行代码中可以直接访问的引用)开始的引用链可以到达某个对象,那么该对象就不会被回收。

  简言之,当我们从任何可执行代码都无法到达某个对象时,它所占用的空间就可以被回收。注意,我们用的是“可以”这个词,因为内存空间是否回收是由垃圾回收器来决定的,通常情况下,只有需要更多的内存空间或者为了避免发生内存溢出时,垃圾回收器才会运行。但是程序可能在没有发生内存溢出,甚至在没有接近内存溢出的时候就退出了,所以可能根本就不需要执行垃圾回收。在当前执行的所有方法中,如果所有变量都不包含指向某个对象的引用,并且从这些变量出发,顺着引用链在所有域或数组元素中也找不到对这个对象的引用,那么我们就说这个对象是“不可达的”。

  垃圾回收意味着我们永远不必担心出现虚悬引用(dangling reference)。在那些可以由程序员直接控制何时删除对象的系统中,程序员可以删除某个其他对象还在引用的对象,如果程序员删除了这样的对象,那么还在引用被删除对象的引用就会变为虚悬的,因为它们引用的是操

  作系统认为是可分配的内存空间(但实际上该空间已经被释放)。系统可以将这个可分配空间分配给新的对象,这样那些原来指向该空间的引用实际上得到的对象与它们所预期的就完全不同了。在这种情况下,当程序使用存储于这个空间中的值并将其当作它们并不属于的对象来操作时,就可能会引起不可预知的灾难。垃圾回收为我们解决了虚悬引用问题,因为所有仍然被引用的对象都不会被当作垃圾回收,所以它们所占用的空间也不可能被释放。垃圾回收同时还解决了意外地多次删除同一个对象的问题—这种问题也会引发灾难。 垃圾对象的回收并不需要我们的介入,但是回收垃圾会占用一定的系统资源。大量对象的创建和回收对时间关键的应用会产生干扰,因此我们在设计这种系统时,要审慎地处理创建的对象数量,以便减少要回收的垃圾数量。

  垃圾回收并不能保证内存总是会有空间来创建新对象。例如,如果我们不停地创建对象,并把这些对象置于某个列表中,那么当没有足够的空间来创建新对象,同时也没有任何未被引用的对象时,就无法再创建新对象了。如果我们让上述列表保持对不再需要的对象的引用,那么就会造成内存泄漏。垃圾回收解决了很多(但并非全部)的内存分配问题。

与垃圾回收器交互
尽管Java语言本身没有任何显式地处置空闲对象的方法,我们还是可以通过直接调用垃圾回收器来寻找不再使用的对象。Runtime类以及system类中的一些便捷方法使得我们可以调用垃圾回收器,请求运行所有待运行的终结器,或者查看当前的内存状态:

  .public void gc Q:该方法请求Java虚拟机花费精力去回收不再使用的对象,以便能够重用这些对象所占据的内存。

  .public void runFinalization():该方法请求Java虚拟机花费精力去运行如下的终结器:那些已经被发现是不可达的,但是其终结器还未执行的对象。

  “public long freememory():返回系统内存可用字节的估测数。

  ·public long total Memory ():返回系统内存的总字节数。

  .public long maxmemoryo:返回Java虚拟机可用的系统内存的最大字节数。如果操作系统对Java虚拟机没有内存使用上的限制,将返回Long . MAX-VALUE. Java中没有任何用来设置系统最大内存的方法,通常,Java虚拟机是通过命令行或者其他配置选项来设置这个值的。

  要调用上述方法,我们需要通过静态方法Runtime.getRuntime来获取对当前Runtime对象的引用。而system类支持静态的gc和runFinalization方法,它们将调用当前Runt-ime对象上的相应方法;换句话说,System.gc()与Runtime.getRuntime().gc()方法是等价的。

  在调用Runtime.gc()方法时,垃圾回收器可能并不能释放出任何额外的内存,因为可能并没有垃圾可以回收,而且并非所有的垃圾回收器都可以按需发现可回收对象。因此调用垃圾回收器可能不会产生任何效果。然而,在创建大量的对象之前,特别是在垃圾回收的开销可能会对其造成影响的时间关键的应用中,调用Runtime.gc()方法还是可取的。执行它有两点潜在的好处:第一点是我们在运行应用程序之前可以得到尽可能多的内存,第二点是我们可以降低执行任务期间垃圾回收器运行的可能性。下面的方法在运行时刻积极地释放了可以释放的所有空间:

  public static vo记ful1GC(){

  Runtime rt=Runtime.getRuntime();

  long isFree=rt.freeMemory ();

  long wasFree;

  do{

  wasFree=isFree;

  rt.runFinalization ();

  rt.gc();

  isFree二rt.freeMemory();

  }while (isFree>wasFree);

  }

  该方法在不断地循环,通过连续调用runFinalization和gc方法,freememory的值不断地增大。当空闲内存的数量不再增大时,该方法的循环也就结束了。

  我们通常不需要调用runFinalization方法,因为finalize方法是由垃圾回收器异步调用的。在某些情况下,例如某项可以由finalize方法回收的资源被耗尽时,通过调用run-Finalization来强制执行尽可能多的终结才会显得有用。但是请记住,我们并不能保证任何等待被终结的对象都在使用这项资源,因此runFinalization可能不会有任何作用。

  fullGc方法对于大多数应用程序来说都显得过于激进。在需要强制进行垃圾回收的特殊情况下,对system.gc方法的单次调用所收集到的垃圾即便不是全部的可利用垃圾,也是其中的绝大部分,因此重复调用会降低垃圾回收的产出率,而且在许多系统中,这些重复调用是毫无产出的。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, 垃圾回收
gc
gc垃圾回收机制、gc垃圾回收机制原理、gc垃圾回收、java gc垃圾回收机制、java中gc垃圾回收机制,以便于您获取更多的相关知识。

时间: 2024-09-11 16:56:21

浅析Java中的GC垃圾回收器的意义及与GC的交互_java的相关文章

深入浅析Java中普通代码块、构造代码块与静态代码块_java

//执行顺序:(优先级从高到低.) 静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1.普通代码块 public static void main(String[] args) { /*普通代码块: *直接定义在在方法或语句中出现"{普通代码的执行语句}"的就称为普通代码块. *普通代码块执行顺序由他们在代码中出现的次序决定--"先出现先执行" * */ { System.out.p

浅析java中ArrayList与Vector的区别以及HashMap与Hashtable的区别_java

就ArrayList与Vector主要从二方面来说.一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的 二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半 就HashMap与HashTable主要从三方面来说.一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现 二.同步性:Hashtable是线程安全的,也就是说是同步的,

浅析Java内存模型与垃圾回收_java

1.Java内存模型 Java虚拟机在执行程序时把它管理的内存分为若干数据区域,这些数据区域分布情况如下图所示: 程序计数器:一块较小内存区域,指向当前所执行的字节码.如果线程正在执行一个Java方法,这个计数器记录正在执行的虚拟机字节码指令的地址,如果执行的是Native方法,这个计算器值为空. Java虚拟机栈:线程私有的,其生命周期和线程一致,每个方法执行时都会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口等信息. 本地方法栈:与虚拟机栈功能类似,只不过虚拟机栈为虚拟机执行J

图片-关于java中释放资源和垃圾回收的问题

问题描述 关于java中释放资源和垃圾回收的问题 后面的ps=null:是为了加速回收吗?什么叫释放资源,感觉有点抽象.可不可以直接=null来回收,为啥要释放资源后回收.求大牛们帮帮我,感激不尽 解决方案 Java中资源回收机制是,一直判断对象是否被使用,在对象在未被使用后会归入回收的行列...当对象被置为null时代表明确告诉系统该对象不再使用,系统就会优先去回收 解决方案二: ps 等于空的赋值,一般是为了防止 ps 被再次使用.因为它已经关闭了! 解决方案三: obj = null,只是

浅析java中stringBuilder的用法_java

String对象是不可改变的.每次使用 System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间.在需要对字符串执行重复修改的情况下,与创建新的 String对象相关的系统开销可能会非常昂贵.如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder类.例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder类可以提升性能. 通过用一个重载的构造函数方法初始化变量,可以创建 Strin

浅谈关于Java的GC垃圾回收器的一些基本概念_java

一.基本回收算法 1. 引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此算法最致命的是无法处理循环引用的问题. 2. 标记-清除(Mark-Sweep) 此算法执行分两阶段.第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除.此算法需要暂停整个应用,同时,会产生内存碎片. 3. 复制(Copying) 此算法把内存空间划为两个相等的区域

浅析Java中的final关键字

谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下面是本文的目录大纲: 一.final关键字的基本用法 二.深入理解final关键字 若有不正之处,请多多谅解并欢迎指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin0520/p/3736238.html 一.final关键字的基本用法 在J

浅析Java中的final关键字(转)

谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下面是本文的目录大纲: 一.final关键字的基本用法 二.深入理解final关键字 若有不正之处,请多多谅解并欢迎指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin0520/p/3736238.html 一.final关键字的基本用法 在J

浅析Java中的反射机制原理

       反射反射,程序员的快乐!        Java中反射机制使用的还是比较广泛的,系统的灵活性.可扩展性大都都是通过反射等方式来加载外部插件,使得系统与插件解耦的同时,增加了功能.但是很多人都只是会用,却是不知道它的实现机制,今天就由我来带大家揭开反射机制的神秘面纱.        Java中是用Class.forName(classname)来反射类. package com.java.reflecttest; import com.java.dbtest.DBTest; /**