论坛首页 Java企业应用论坛

Java中的垃圾回收与对象生命周期

浏览 18256 次
精华帖 (5) :: 良好帖 (2) :: 新手帖 (5) :: 隐藏帖 (1)
作者 正文
   发表时间:2010-06-21  
maozj 写道
joehe 写道
i2534 写道
J-catTeam 写道
比如: 
       不要写成: 
       for (int i = 0; i < 10000; i++) { 
             Object obj = new Object(); 
             System.out.println(obj); 
       } 
 
       要写成: 
       Object obj = null; 
       for (int i = 0; i < 10000; i++) { 
             obj = new Object(); 
             System.out.println(obj); 
       }

看应用场景的

貌似前几天javaeye上有个帖子阐述了这个问题,说的是两个方式现在的jvm已经是一样的速度了.


这点不错,不能一概而论,会误导观众的

你能说说这两段代码的区别吗


这两代码都生成了10000个对象,楼主对引用的理解有误。第二段代码中,相对与第一段而言,少开辟了几个栈对象,也就是说Object obj只是个一个标示,关键是new了10000次,因此在执行效率和内存消耗没有不同,只是变量的作用域变化了。
0 请登录后投票
   发表时间:2010-06-21  
已修正~~ 写的很好
0 请登录后投票
   发表时间:2010-06-21  
mercyblitz 写道
maozj 写道
joehe 写道
i2534 写道
J-catTeam 写道
比如: 
       不要写成: 
       for (int i = 0; i < 10000; i++) { 
             Object obj = new Object(); 
             System.out.println(obj); 
       } 
 
       要写成: 
       Object obj = null; 
       for (int i = 0; i < 10000; i++) { 
             obj = new Object(); 
             System.out.println(obj); 
       }

看应用场景的

貌似前几天javaeye上有个帖子阐述了这个问题,说的是两个方式现在的jvm已经是一样的速度了.


这点不错,不能一概而论,会误导观众的

你能说说这两段代码的区别吗


这两代码都生成了10000个对象,楼主对引用的理解有误。第二段代码中,相对与第一段而言,少开辟了几个栈对象,也就是说Object obj只是个一个标示,关键是new了10000次,因此在执行效率和内存消耗没有不同,只是变量的作用域变化了。


-------------------------
已修正~~
0 请登录后投票
   发表时间:2010-06-21  
maozj 写道
wangzaixiang 写道
写了很多,错误不少。
1. 而栈内存则是用来存储程序代码中声明为静态或非静态的方法。
完全错误的表达。

2、为对象分配存储空间;
       <2> 开始构造对象;
       <3> 从超类到子类对static成员进行初始化;
       <4> 超类成员变量按顺序初始化,递归调用超类的构造方法;
       <5> 子类成员变量按顺序初始化,子类构造方法调用。
static的初始化与new操作没有任何关系。

3、比如:
       不要写成:
       for (int i = 0; i < 10000; i++) {
             Object obj = new Object();
             System.out.println(obj);
       }

       要写成:
       Object obj = null;
       for (int i = 0; i < 10000; i++) {
             obj = new Object();
             System.out.println(obj);
       }
完全错误。两者在运行时几无差别,前置在编码风格上更为合理。

4、 (5) 可收集阶段、终结阶段与释放阶段
       当一个对象处于可收集阶段、终结阶段与释放阶段时,该对象有如下三种情况:

       <1> 回收器发现该对象已经不可达。

       <2> finalize方法已经被执行。

       <3> 对象空间已被重用。
前面的理解都不正确,这里的表述更为问题多多。

1. 而栈内存则是用来存储程序代码中声明为静态或非静态的方法。
完全错误的表达。  请您解释下?

2. static的初始化与new操作没有任何关系。放屁

3.完全错误。两者在运行时几无差别,前置在编码风格上更为合理。 理由?

4. 请解释。


呵呵,我来解释吧,首先楼主,你要明白一点,wangzaixiang说的是对的。为什么?

1.栈内存是由栈帧(frame)组成的,在Java代码中的,每一行执行代码称为一帧。比如Object obj=null;obj这样的标示对象会保存在栈里面。同时,方法参数对象标示也在栈中。对象的实际物理保存都在堆中。由于Java的重进入,
所以栈对象是线程安全,而堆是JVM线程共享的,因此需要合理的同步。

2.确实没有关系,static成员隶属于类对象,类的static成员的初始化是在ClassLoader第一次加载该类的时候。和new确实没有什么关系,只不过第一次出现new SomeObject的时候,会加载SomeObject,然后静态成员初始化了。楼主这里就误会了,不一定new 才是加载类的开始,通过调用类的静态可访问的方法也是可以的。

3.确实没有差别,理由:这两代码都生成了10000个对象,楼主对引用的理解有误。第二段代码中,相对与第一段而言,少开辟了几个栈对象,也就是说Object obj只是个一个标示,关键是new了10000次,因此在执行效率和内存消耗没有不同,只是变量的作用域变化了。

4.我的理解是:
  <1> 比如方法中的局部对象,并不需要JVM标记不可达,在方法执行完之后,马上就被回收。这就是为什么不需要在局部对象使用后,显示地设置为null.
  <2>finalize 不一定可靠,或者被调用。规范中没有规定,垃圾收集器必须要在对象回收时,调用这种方法或者并不是每个对象回收时均被调用。不等同于free或者C++的析构。
  <3>重用是肯定的,但是对象空间能不能马上重用,很难说,G1的算法和CMS等算法不同。G1是等大小区域,相对来说比较容易。CMS,我没有记错的话,是采用的碎片空间移动。



0 请登录后投票
   发表时间:2010-06-21  
对楼主提出的软应用的好处还是不太理解。
比如为什么
"软引用技术的引进使Java应用可以更好地管理内存,稳定系统,防止系统内存溢出,避免系统崩溃"???
0 请登录后投票
   发表时间:2010-06-22  
J-catTeam 写道
比如: 
       不要写成: 
       for (int i = 0; i < 10000; i++) { 
             Object obj = new Object(); 
             System.out.println(obj); 
       } 
 
       要写成: 
       Object obj = null; 
       for (int i = 0; i < 10000; i++) { 
             obj = new Object(); 
             System.out.println(obj); 
       }

看应用场景的


这样写会容易出现陷阱。
我倒觉得
             Object obj = new Object();  
             System.out.println(obj); 
             obj = null;

这个会帮助GC
0 请登录后投票
   发表时间:2010-06-22   最后修改:2010-06-22
晚上再看看帖子,略有感触。

1、这个初哥不理解我的问题也就罢了,放屁的词语也出来了。现在,不知道到底明白是我在放屁还是楼主搞错了。

2、谢谢mercyblitz替我回复,与我的表述基本相符,但可能存在笔误,我再修订一下。

每一行执行代码称为一帧 =》 应为每一次函数调用对应一帧。

引用
确实没有差别,理由:这两代码都生成了10000个对象,楼主对引用的理解有误。第二段代码中,相对与第一段而言,少开辟了几个栈对象,也就是说 Object obj只是个一个标示,关键是new了10000次,因此在执行效率和内存消耗没有不同,只是变量的作用域变化了。

其实,第二段代码和第一段代码在帧上分配的变量是一样的,也是一个栈变量(不合适成为栈对象)。

4、当对象处于释放状态后,空间状态为“已被重用”,这个是典型的字面翻译,其错误不值一提。

感觉楼主应该是一个很好学的程序员,不过,目前,Java水平还处在幼儿园级别,谦虚程度又颇有博士生的感觉。谈到放屁二字,我稍微吹吹水,在JVM上,我小有10余年研究,不算专家的话,也是略有精通的人了。本想指点楼主一二,却可惜被反批了一顿,笑笑飘过。

0 请登录后投票
   发表时间:2010-06-22  
而栈内存则是用来存储程序代码中声明为静态或非静态的方法

请问楼主,你自己明白是什么意思吗?麻烦你把那段英语原文贴出来,再好好查查字典。
码字其实并不重要,真正消化理解才是正章。
0 请登录后投票
   发表时间:2010-06-22  
maozj 写道
joinhack 写道
  for (int i = 0; i < 10000; i++) { 
             Object obj = new Object(); 
             System.out.println(obj); 
       } 
 
       要写成: 
       Object obj = null; 
       for (int i = 0; i < 10000; i++) { 
             obj = new Object(); 
             System.out.println(obj); 
       }
大家都感觉作者说的是错误的,但是并没有说出为什么,因此作者毛了,呵呵
其实,作者的意思是这么写会造成很多引用留在栈里面,但是作者还有个东西没有考虑,就是作用域。
句柄会随着作用域消失而消失,因此上面的2种写法,对于句柄来说不会不断扩大,作者可以放心使用。

恩 成很多引用留在栈里面 说的正确。。。
Object obj = null;  后者还多了一条初始化

您的说法 完全接受。。。 表述不错 足见很有方法哲理~~


虽然会冒着被骂的风险,还是在指点楼主两句。“成很多引用留在栈里面 说的正确”的理解还是错的。告诉你一个结果,第一段代码,哪怕你循环100万次,你需要的内存和循环1次是一样多的,栈中也只有一个引用。

再给你一点为学的指点:很多时候,你说明白了,你还真傻也不明白,如果你知道你其实不明白,可能比你认为自己明白更明白,然后你才有可能明白,否则,你以为明白了,永远也不会明白,却一直以为自己明白,其实不明不白。而要想明白,需要谦虚一些,低调一些,不要不懂装懂,或者看点皮毛,就迫不及待的觉得发现了真理。慢慢的,或许你会明白,不过,如果你还是不明白,那就慢慢的去明白吧。
0 请登录后投票
   发表时间:2010-06-22   最后修改:2010-06-22
mercyblitz 写道

  <3>重用是肯定的,但是对象空间能不能马上重用,很难说,G1的算法和CMS等算法不同。G1是等大小区域,相对来说比较容易。CMS,我没有记错的话,是采用的碎片空间移动。




CMS缺省是不做碎片处理的。G1则是。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics