java垃圾回收 - 为什么要进行垃圾回收

1、为什么要进行垃圾回收:

       在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象 的内存时,该内存便成为垃圾。 垃圾回收能自动释放内存空间,减轻编程的负担,JVM的一个系统级线程会自动释放该内存块。垃圾回收意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对 象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾回收也可以清除内存记录碎片。由于创建对象和垃圾回收器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。

2、如何进行垃圾回收:

Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾回收算法一般要做2件基本的事情:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。

   大多数垃圾回收算法使用了根集(root set)这个概念;所谓根集就是正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和 调用对象的方法。垃圾回收首先需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间 接可达的对象。

3、对于特殊区域的垃圾回收(比如调用cc语言中的malloc()函数进行空间的分配那么垃圾回收机制就不能回收这类特殊空间): 之所以要使用finalize(),是存在着垃圾回收器不能处理的特殊情况。假定你的对象(并非使用new方法)获得了一块“特殊”的内存区域,由于垃圾 回收器只知道那些显示地经由new分配的内存空间,所以它不知道该如何释放这块“特殊”的内存区域,那么这个时候java允许在类中定义一个由 finalize()方法

4、触发GC(Garbage Collector)的条件:

 JVM进行次GC的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是主GC的触发条件,因为它对系统影响很明显。总的来说,有两个条件会触发主GC:

  1)当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,但以下条件除外。

  2)Java堆内存不足时,GC会被调用。 当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足 内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则 JVM将报“out of memory”的错误,Java应用将停止。

5、减少GC开销的措施:

  1. 不要显示的调用System.gc()
  2. 尽量减少临时对象的使用
  3. 对象不用的时候最好显示置空
  4. 尽量使用StringBuffer,不实用String累加字符串(String的特性有关)
  5. 能使用基本数据类型就不要使用封装类
  6. 尽量减少静态对象变量的使用

6、注意:

  1. GC的回收时间是不确定的,即使你显示的调用的System.gc()。因为和线程优先级有关
  2. 使用了finalize()方法之后,GC是在这个方法执行之后的下一次进行垃圾的回收。

原文地址:https://www.cnblogs.com/laojiao/p/9689590.html

时间: 2024-08-01 03:32:57

java垃圾回收 - 为什么要进行垃圾回收的相关文章

深入理解JAVA虚拟机之JVM性能篇---垃圾回收

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

Java中的内存分配与垃圾回收

一.内存分配 Java程序运行时的内存分配,按照JVM规范,包括以下几个区域:程序计数器.虚拟机栈.本地方法栈.方法区.堆.其中,前三个是线程私有的,与线程生命周期相同,线程退出内存自动回收:后两者是所有线程共享内存的,只在垃圾回收机制被触发时,被动回收. * 程序计数器,内存区域极小,是当前线程的字节码执行行号指示器: * 虚拟机栈.本地方法栈,即平时所说的“栈”,是虚拟机用来执行方法(包括Java.非Java方法)时,使用的临时内存空间,用来存储当前方法.局部变量等,全部基本类型变量,以及类

(转)《深入理解java虚拟机》学习笔记3——垃圾回收算法

Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这三个区域的内存分配和回收都具有确定性.垃圾回收重点关注的是堆和方法区部分的内存. 常用的垃圾回收算法有: (1).引用计数算法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器都为0的对象就是不再被使用的,垃

Java工作原理:JVM,内存回收及其他

JAVA虚拟机系列文章 http://developer.51cto.com/art/201001/176550.htm Java语言引入了Java虚拟机,具有跨平台运行的功能,能够很好地适应各种Web应用.同时,为了提高Java语言的性能和健壮性,还引入了如垃圾回收机制等新功能,通过这些改进让Java具有其独特的工作原理. 1.Java虚拟机 Java虚拟机(Java Virtual Machine,JVM)是软件模拟的计算机,它可以在任何处理器上(无论是在计算机中还是在其他电子设备中)安全兼

所有做java开发的都是些垃圾

所有做java开发的都是些垃圾,再垃圾的框架,只要有人用,对java程序员来说那就是高性能,高可用,解耦的,非常优秀的一款框架.属于吃屎都吃的津津有味.java里的框架都是垃圾,连一个不错的都没有.比如struts这个垃圾,返回一个SUCCESS,呵呵!而且不配置的话,一个动作类只能有一个方法.哪个坐井观天的脑残写的.现在最流行的mybatis框架,把所有sql配置到xml.把xml也算是玩到极致了.你无法想象世上竟然有这种垃圾.做java开发的为什么都这么垃圾.还有java接口现在可以有方法的

易宝典文章——玩转Office 365中的Exchange Online服务 之二十四 配置垃圾邮件筛选器反垃圾邮件

如果希望实现基于发件人邮件地址,或者需要拒绝某个域的邮件,可以通过Exchange Online提供的垃圾邮件筛选器策略来解决.垃圾邮件筛选器策略除了能够实现上述的黑名单筛选外,还支持白名单筛选,基于国别来进行筛选,比如阻止某岛国语言的邮件,从某小人国发来的邮件等.此外,垃圾邮件筛选器策略还定义做针对不同级别的垃圾邮件如何进行处理,是标注,还是放入垃圾箱,或者是进行隔离等.一.了解默认的垃圾邮件筛选器策略在EAC中,导航到"保护",定位到"垃圾邮件筛选器"选项卡,选

Java进阶之内存管理与垃圾回收

Java是在JVM所虚拟出的内存环境中运行的.内存分为栈(stack)和堆(heap)两部分.我们将分别考察这两个区域. 栈 在Java中,JVM中的栈记录了线程的方法调用.每个线程拥有一个栈.在某个线程的运行过程中,如果有新的方法调用,那么该线程对应的栈就会增加一个存储单元,即帧(frame).在frame中,保存有该方法调用的参数.局部变量和返回地址. 调用栈 Java的参数和局部变量只能是基本类型的变量(比如int),或者对象的引用(reference).因此,在栈中,只保存有基本类型的变

Java内存回收(2)——垃圾回收算法

如果还没看过第一篇的朋友请移步:JAVA内存回收(1)-深入浅出Java垃圾回收机制 任何垃圾收集算法必须完成两件事情.首先,它必须检测出垃圾对象.其次,它必须回收垃圾对象所占用的堆空间并使之对程序重新可用. 垃圾检测通常通过定义一个根引用集并计算其可达对象集的方式来实现.一个对象,如果可以通过某条始于根引用的引用路径而被执行程序访问到的话,则称其为可达的(reachable).对程序而言,根引用始终是可以访问的.一个对象如果是可达的,则称其为活动对象:否则就被称为垃圾,因为它对程序的未来执行不

java基础四 [构造器和垃圾回收](阅读Head First Java记录)

本章讲解了对象的创建到被回收的过程,讲述了对象的生命周期 堆(heap)与栈(stack) 实例变量:实例变量是只声明在类下,方法外的变量(实例变量默认值为0/0.0/false,引用的默认值为null) 局部变量:声明在方法中的变量,或方法中的参数.又被成为栈变量 例如: public class test{ int size; public void foof(int a){ int b; barf() } public void barf(){ Duck d =new Duck(24);