解决方案 »

  1.   

    垃圾回收主要指堆和方法区的内存回收,由于方法区垃圾回收比较苛刻, 所以字符串常量池从JDK7后由方法区移出,但不论在哪它都在gc的范围之内,finalized方法算是个奇葩,任何一个对象,在被gc之前都会且只会被调用一次finalized,但并不保证被完整的执行,没有任何理由需要重写finalized方法,也就是这个方法对于程序员而言一点用处都没。将引用设置为null只是将对象从Gc Roots上断开,等待下次垃圾回收。
    不同的垃圾收集器针对自己内存区域的特定采用不同的收集算法,“标记-复制”算法简单,执行效率高但浪费内存,但由于其高效性,堆新生代中一直使用的这个算法,“标记-清理"算法复杂,需要更复杂的收集器来支持。 
      

  2.   

    楼上大神回答的不错。你可以看下http://blog.csdn.net/u014496722/article/details/27639171应该能比较详细的回答你的第三个问题。
      

  3.   

    1.java的对象不一定会被gc回收。 问下 不用new关键字创造的特殊对象 有哪几种? String s ="ss";算吗? 字符串池不在gc的回收范围吗? 
    java的对象不一定会被gc回收。 
    扯,如果有对象不能被gc,这叫做“内存泄露”,迟早内存会爆。
    不用new关键字创造的特殊对象 有哪几种?
    创建的对象就是对象,无所谓特殊。不用new也可以创建,反射可以创建对象
    String s ="ss";算吗?
    这里的"ss"存在于常量池里,是常量池里的一块内存,不能算做是对象。不过实践中不用分的那么清楚,只要知道怎么用s这个变量去操作字符串就行了
     字符串池不在gc的回收范围吗?
    不对,刚才解释了预定义的常量字符串在常量池里,常量池是属于class的,class是在方法区的。所以你所说的“字符串池”是在方法区里,也是在gc回收范围之内的。有兴趣可以去google:class load unload2.finalized() 并不是c++的析构方法?为什么调用System.gc() 不一定要调用finalized()? 在这里对象的终结条件怎么理解? 怎么自己重写finalized() ?将将回收的对象的引用 置为null?将流引用的文件关闭?
    finalized() 并不是c++的析构方法?
    正确。java里的finalized方法和c++里的语义不一样
    为什么调用System.gc() 不一定要调用finalized()?
    finalized只会被调用一次,如果调用过一次之后这个对象还没有被回收,等到它真正被回收的时候,finalized却不会再次被调用了。
     在这里对象的终结条件怎么理解? 怎么自己重写finalized() ?
    不需要重写。写了这么多年java,从来没有重写过。因为上面解释的原因,finalized并不能当作c++里的内存释放一样来使用,并且不保证一定在gc的时候被调用,所以java里这是一个不靠谱的东西,实践中是从来不用的
    将将回收的对象的引用 置为null?将流引用的文件关闭?
    这个操作是必须的,原因不用我来说了吧。一般放在finally里做,保证打开的资源一定被释放
    3.为啥说java的gc不能完全代替 c的析构? 能探讨下 gc的两种工作 “暂停-复制" 和 "标记-清理"的模式吗? 堆内碎片多gc就会切换“暂停-复制",程序稳定时调用"标记-清理" 说说吧,这是我看think in java的疑惑
    为啥说java的gc不能完全代替 c的析构?
    个人认为差别不大。java里是JVM来帮你做gc的工作,析构是自己手动释放,想什么时候释放什么时候释放,我想区别可能在这里吧。从效果上来看,我觉得差不多。毕竟都是做的内存释放的工作,没听说过java在内存释放上有问题导致用不了
    能探讨下 gc的两种工作 “暂停-复制" 和 "标记-清理"的模式吗?
    这种网上资料太多了,不赘述,自己去搜索。笼统的来说,就是两种不同的思路算法
     堆内碎片多gc就会切换“暂停-复制",程序稳定时调用"标记-清理" 
    复制算法会把被小对象分割开的内存碎片放到一起,让内存使用更有效率。
      

  4.   

    gc回收内存是有一定的算法,如果你想创建一个gc回收不了的java对象,是完全可以的。但这种对象具有很大的危险性,有可能导致内存溢出。
      

  5.   

    4楼 给你回复的  差不多!补充下:java 对象不能被gc 回收掉 那就是 内存泄露。java 不一定通过new ,别忘了 有反射。但一个类初始化的 需要在4种 字节码指令下才会触发(new getstatic putstatic  invokestatic)。String s ="s" 也是种。 难道你忘了所有对象的父类都是 Object? 常量池在方法区。 方法区同样属于堆 ,自然而然在gc内 。方法  接口 字段 都一样 ,只是他们有自己回收的条件。 暂停-复制?  应该叫做 标记-复制,  也就是先标记出需要清除的对象 ,然后在复制到堆某一端, 这种方式可以解决碎片问题,但是它比较占用堆空间,所以就出现了 标记-整理-清楚 先标记 把要清除的对象全部移动到一起然后在清除,  为什么有暂停一说,就好比 你妈给你打扫房间 ,你是不是 停下来 产生垃圾行为 ,让你妈清理?  但是不暂停的话,你妈给你打扫一次房间,你一边丢,那产生的新垃圾 你妈不停的给你打扫 还是 等待下一次打扫时 在打扫呢?  
      

  6.   

    C/C++的析构处理,给出了程序统一释放内存、解除I/O操作(数据库连接、网络连接、文件操作等)的时机
    但是具体的释放和解除操作都得程序员自己手动编写代码来完成,
    包括先释放/解除谁,后释放/解除谁这些细微的顺序如果搞错了,都有可能导致整个程序崩溃
    不过这符合C语言的哲学:“程序员应该知道自己在做什么”Java的GC,在JVM认为合适的时机下,自动的帮助程序员释放内存,主要目的是为了减少内存泄露造成的不易察觉的Bug
    但是,仅仅依靠GC,并不能解除如:数据库连接、网络连接、文件操作等I/O操作
    需要自己在合适的时机下(一般为finally代码块中),手动调用close方法具体的讨论可以参考下面的帖子
    http://bbs.csdn.net/topics/390812239Q:为啥说Java的GC不能完全代替C/C++的析构?
    A:书写良好的C/C++的析构 约等于 Java的GC(自动释放内存) + finally中的close(手动解除I/O操作)