`
kakaluyi
  • 浏览: 444403 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Finalize 和 GC的区别

阅读更多

finalize()是由JVM自动调用的,你可以用System.gc(),但JVM不一定会立刻执行,JVM感觉内存空间有限时,才会开始执行finalize(),至于新的对象创建个数和被收集个数不同是因为收集的对象只和JVM的垃圾收集策略有关。


1.构造函数
要点:
构建器(Constructor)属于一种较特殊的方法类型,因为它没有返回值.这与 void返回值存在着明显的区别。对于void返回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构建器则不同,它不仅什么也不会自动返回,而且根本不能有任何选择.若创建一个没有构件器的类,则编译器会自动创建一个默认构件器.

2.finalize()和gc()

(1)问题:finalize()函数是干嘛的?Java不是有Garbage Collection(以下简称gc)来负责回收内存吗?
回答:
gc 只能清除在堆上分配的内存(纯java语言的所有对象都在堆上使用new分配内存),而不能清除栈上分配的内存(当使用JNI技术时,可能会在栈上分配内存,例如java调用c程序,而该c程序使用malloc分配内存时).因此,如果某些对象被分配了栈上的内存区域,那gc就管不着了,对这样的对象进行内存回收就要靠finalize().
举个例子来说,当java 调用非java方法时(这种方法可能是c或是c++的),在非java代码内部也许调用了c的malloc()函数来分配内存,而且除非调用那个了 free() 否则不会释放内存(因为free()是c的函数),这个时候要进行释放内存的工作,gc是不起作用的,因而需要在finalize()内部的一个固有方法调用它(free()).
finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存.所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作.

(2)问题:finalize()在什么时候被调用?
回答:

有三种情况

1.所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候.
2.程序退出时为每个对象调用一次finalize方法。
3.显式的调用finalize方法

除此以外,正常情况下,当某个对象被系统收集为无用信息的时候,finalize()将被自动调用,但是jvm不保证finalize()一定被调用,也就是说,finalize()的调用是不确定的,这也就是为什么sun不提倡使用finalize()的原因.


3. this
要点:
this关键字只能在方法中使用,它能为调用该方法的对象提供相应的句柄,使得同一个类产生的不同对象实例在调用同一方法的时候,系统能判断出是哪一个对象在进行调用.
比如:
MyObject a=new MyObject();
MyObject b=new MyObject();
a.f();// (3)
b.f();// (4)
编译器在编译的时候,实际上是将(3),(4)句解释为
MyObject.f(a);
MyObject.f(b);
的,这样就将调用了该方法的对象的信息传到了方法中,也就是传给了this,就可以通过this表示调用该方法的对象实例.

用this的概念还可以解释为什么在静态方法中不能调用非静态方法和元素,这是因为静态方法中没有this,也就是说我们不能获得调用该方法的对象的句柄.既然找不到这个对象实例,我们又怎么能够在其中调用对象实例的方法和元素呢?

那为什么静态方法没有this呢?用静态方法的概念可以来理解这个问题.静态方法是类方法,是所有对象实例公用的方法.它不属于某一个具体的对象实例,因此也无法用this来体现这个实例.这和非静态方法是不一样的.打个比方,在一个局域网内的几个用户每个人都有一台客户机,但都访问一台公共的服务器.对于每台客户机来说,它的this就是使用它的用户.而对于服务器来说,它没有this,因为它是大家公用的,不针对某一个具体的客户.

4.对象初始化
要点:
1.对象只有在创建的时候,需要使用它的时候才进行初始化,否则永远都不会初始化.
2.对象进行初始化是有一定顺序的,无论在定义的时候各个成员的摆放位置如何.首先是静态成员和对象,然后是非静态成员和对象,最后才运行构造器.
3.静态成员和对象有且只有一次初始化过程,这个过程发生在第一次创建对象或者第一次使用类的静态成员和对象的时候.

以一个名为Dog的类为例,它的对象实例初始化过程如下:
(1) 类型为Dog的一个对象首次创建时,或者Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在事先设好的类路径里搜索)。
(2) 找到Dog.class后,它的所有static初始化模块都会运行。因此,static初始化仅发生一次?D?D在Class对象首次载入的时候。
(3) 创建一个new Dog()时,Dog对象的构建进程首先会在内存堆(Heap)里为一个Dog对象分配足够多的存储空间。
(4) 这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值
(5) 进行字段定义时发生的所有初始化都会执行。
(6) 执行构建器。正如第6章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时候

5.数组的初始化
数组包括基本数据类型数组和对象数组,其中对于对象数组的初始化,经常会出现"Exception"错误.比如下面的程序

问题代码如下:

public userInfo[] getUsersInfo() {

userInfo[] usersInfo=null;

if (users.size()!=0) {
usersInfo=new userInfo[users.size()];

for(int i=0;i< usersInfo.length;i++) {
//+-------------------出问题的地方-----------------
usersInfo[i].name=((User)(users.elementAt(i))).name;
usersInfo[i].type=((User)(users.elementAt(i))).type;
usersInfo[i].userID=((User)(users.elementAt(i))).userID;
//+-------------------出问题的地方-----------------
}
System.out.println("here");
return usersInfo;
}else {
return null;
}
}



其中userInfo的定义为

class userInfo{
userInfo(String name,int type,int userID){
this.name=name;
this.type=type;
this.userID=userID;
}
String name;
int type;
int userID;
}



运行到程序中标出的问题区域时,系统显示NullPointerException,为什么会这样呢?

这是因为,Java在定义数组的时候
usersInfo=new userInfo[users.size()];
并没有给数组元素分配内存,它只是一个句柄数组,数组中的对象还没有初始化.因此数组中的每个对象都需要new之后才可以访问.例如:
A[] a=new A[2];
for(int i=0;i<2;i++)
a[i] = new A();
这样才能a[i].someMethod()

因此上面的程序应该改为

public userInfo[] getUsersInfo() {

userInfo[] usersInfo=null;

if (users.size()!=0) {
usersInfo=new userInfo[users.size()];

for(int i=0;i< usersInfo.length;i++) {
//+-------------------修改的地方-----------------
usersInfo[i]=new userInfo(((User)(users.elementAt(i))).name,
((User)(users.elementAt(i))).type,
((User)(users.elementAt(i))).userID);
}
//+-------------------修改的地方-----------------
return usersInfo;
}else {
return null;
}
}


就没问题了简单来讲,finalize()是在对象被GC回收前会调用的方法,而System.gc()强制GC开始回收工作纠正,不是强制,是建议,具体执行要看GC的意思简单地说,调用了 System.gc() 之后,java 在内存回收过程中就会调用那些要被回收的对象的 finalize() 方法。

分享到:
评论

相关推荐

    final, finally, finalize的区别

    在Java编程语言中,"final", "finally", 和 "finalize" 这三个关键字有着截然不同的含义和用途,它们各自在程序设计的不同层面扮演着重要角色。深入理解这些概念对于编写高效、健壮的Java代码至关重要。 ### final ...

    【IT十八掌徐培成】Java基础第26天-03.JVM结构-finalize-gc.zip

    Java是世界上最流行的...通过深入理解JVM的结构、`finalize`机制以及GC的工作方式,开发者能够更好地优化Java应用程序的性能,预防和解决内存问题。这不仅是Java程序员的基础知识,也是进阶为高级开发者的关键技能。

    Java中finalize()的用法

    Java 中 finalize() 的用法 Java 中的 finalize() 方法是垃圾回收器在回收对象时调用的第一个方法。...finalize() 方法是 Java 中的一种机制,用于释放对象占用的系统资源,但需要正确地使用和注意其调用机制和限制。

    垃圾回收finalize的用处(算法 演示)

    垃圾回收是Java与C++等其他语言的一大区别,它使得程序员无需手动管理内存,提高了开发效率和程序的健壮性。然而,尽管Java的垃圾回收机制在大多数情况下可以正常工作,但有时我们需要对某些特定对象的清理进行特殊...

    c#中的非托管资源释放 (Finalize和Dispose)

    ### C#中的非托管资源释放 (Finalize和Dispose) 在深入了解`Finalize`与`Dispose`之前,我们首先需要理解两个基本概念:托管资源与非托管资源。 #### 托管资源与非托管资源 1. **托管资源**指的是由.NET运行时...

    C#基础:Dispose()、Close()、Finalize()的区别详解

    在C#编程中,了解如何正确管理对象生命周期和释放资源是至关重要的。本文将深入探讨三个关键的方法:`Dispose()...理解这些方法的区别和使用场景,可以帮助你编写更健壮、高效的C#代码,避免资源泄漏和其他潜在的问题。

    Java中finalize方法使用.doc

    Java 中 finalize 方法使用 finalize 方法是 Java 编程语言中一个非常重要的方法,它与 Java 编程中的垃圾回收器有着紧密的关系。当一个对象变成一个垃圾对象的时候,如果此对象的内存被回收,那么就可以调用系统中...

    java虚拟机中gc的基本原理 .docx

    理解GC的基本原理对于优化Java应用的性能至关重要,尤其是在对性能要求较高的场景,如嵌入式系统和实时系统。 GC的基本原理主要涉及到对象的生命周期管理和内存的自动回收。当程序员通过`new`关键字创建一个对象时...

    优秀的Java程序员必须了解GC的工作原理

    在Java中,GC通常使用有向图结构来记录和管理堆(heap)中的所有对象,以此来判断哪些对象是可达的,哪些是不可达的。当GC发现某些对象不再可达时,它们的内存空间就会被回收。 尽管GC的基本任务是明确的,但Java规范...

    优秀Java程序员必须了解的GC工作原理

    GC的主要任务是自动管理内存,尤其是对象的分配和回收,以避免内存泄漏和资源浪费。在Java中,程序员通过`new`关键字创建对象,而对象的释放则无需手动操作,只要将对象的所有引用置为`null`,使其变为“不可达”,...

    从JVM的内存管理角度分析Java的GC垃圾回收机制.docx

    总的来说,Java的GC机制是一个复杂而重要的主题,理解其工作原理,掌握如何与之协作和优化,对于提升Java程序的性能和稳定性至关重要。开发者需要不断学习和实践,以便在实际项目中做出最佳的内存管理决策。

    rust-gc:用于Rust的简单跟踪(标记和清除)垃圾收集器

    锈-gc 用于Rust的简单跟踪(标记和清除)垃圾收集器 ... 放置在Gc类型必须实现Trace和Finalize 。 最简单的方法是使用gc_derive板条箱: use gc :: {Finalize, Gc, Trace}; #[derive(Trace, Finali

    简单理解Java的垃圾回收机制与finalize方法的作用

    `finalize()`方法是在对象被GC标记为可回收并准备释放之前调用的,提供了在对象被彻底删除前执行某些清理操作的机会。通常,当一个对象不再被任何引用可达时,GC会先调用其`finalize()`方法,然后在下一次垃圾回收时...

    Java程序员面试宝典 PDF 参考资料.rar

    Java程序员面试宝典 pdf,内容涉及String、Servlet、int 和 Integer的区别、、String 和StringBuffer的区别、运行时异常与一般异常有何异同、Servlet的生命... Collections的区别、HashMap和Hashtable的区别、final...

    浅析final,finally,finalize 的区别

    下面我们将详细解析这三个关键字的区别和用途。 1. **final** - **final 修饰类**:当 `final` 关键字用于修饰类时,意味着该类不能被其他类继承,它是一个最终类或顶级类。例如,`java.lang.Object` 类就是 `...

    Java垃圾回收finalize()作用详解

    总的来说,Java的`finalize()`方法提供了一种在对象被垃圾收集器回收前进行额外操作的机会,但这应该谨慎使用,因为它的执行时间和效果都是不确定的。在设计程序时,优先考虑使用Java提供的自动资源管理机制,如`try...

    04.GC要做的事情1

    GC(Garbage Collection)是Java虚拟机中一个非常重要的组件,负责回收Java堆和方法区中不再使用的对象,以避免内存泄露和溢出。那么,GC要做的事情是什么? 首先,GC需要确定哪些内存需要被回收。Java虚拟机中,...

    Java GC 专题

    Java GC有多种不同的实现,包括串行GC、并行GC、并发Mark Sweep (CMS) 和G1(Garbage-First)GC等。串行GC适合轻量级应用,它在一个单独的线程中运行,对性能影响较小。并行GC则在多个CPU核心上同时进行,提高了效率...

    白话说java gc垃圾回收.docx

    Java垃圾回收(GC)是Java语言的一大特性,它自动化地管理程序内存,使得开发者无需手动进行内存分配和释放,从而避免了C/C++等语言中常见的内存泄漏问题。GC通过智能地识别并回收不再使用的对象,确保内存的有效...

    「入门篇」初识JVM (下下) - GC.doc

    其中,垃圾收集(GC)主要针对的是堆和方法区。 【垃圾收集(GC)】 垃圾收集是JVM自动管理内存的过程,用于回收不再使用的对象所占用的空间,避免内存泄漏。GC主要关注的是堆和方法区,因为这两个区域存储的是线程...

Global site tag (gtag.js) - Google Analytics