java为什么样不提供类似c的析构函数和delete?这段代码有没有正确释放堆栈空间
我知道c会有内存泄露的可能,但对象delete后就立刻执行析构函数。
而java的回收则是引用赋值为null,等待gc回收,即使调用System.gc()回收时间也是不确定的,不是立刻回收的。
所以我有个疑惑,为什么java不提供类似delete和析构函数这样的方法呢?这样不是能很快的回收用完的内存,减轻gc负担么?为什么非要等着系统调用gc才能回收呢?
就如@林俊 说的,java内存的管理是由jvm负责的,这样就不需要程序员自己去手动释放空间了,能够减少许多工作量也降低的java语言本身的门槛。但其实java是提供类似析构函数的功能的,就是finalize方法。当gc要释放对象时就会调用改对象的finalize方法。当然,由于gc的回收是不能预测的,对于那些急需要释放的资源(例如,TCP连接等),通常不是在finalize方法里完成的,而是提供①个类似close这样的方法,让调用者可以在gc回收之前手动先释放那些可以控制的资源。
我都不记得java对象被回收时调用的方法叫什么了,反正不推荐用的,因为你不知道对象什么时候会被回收。
与C++的析构函数对应的,是finally block。
Java的内存管理方式注定它没有C++那样让人放心的析构函数
请问题主问的是堆(heap)还是栈(stack)?我不喜欢堆栈这个词所以我的回答里会完全避免使用它,免得起歧义。
栈的话,纯Java代码是没办法泄漏栈空间的,它完全被JVM掌控,Java代码无法创建任何指向栈空间的指针所以无从谈起泄漏栈空间。反正①个方法每被调用①次,入口出会分配栈空间,出口处会释放栈空间,就这么简单,没办法出错。
堆的话,这里大概想问的是最后那个 img = null 是否足以释放 img 指向的 Image[] 数组。
简单答案是:这个赋值是完全多余的,没有任何必要在方法临返回前给引用类型的局部变量赋值为null。这个赋值并不会帮助GC回收 img 所指向的 Image[] 数组;就算没有这个赋值GC也可以在它选择的时机正确回收该数组。
要看更长的解释的话请跳传送门(特别是里面开头的那个传送门):这段 Java 代码中的局部变量能够被提前回收吗?编译器或 VM 能够实现如下的人工优化吗? - RednaxelaFX 的回答
没耐心看完这个传送门的话,上面的简单答案就够用了。
不过要额外注意的是,这个代码例子里有个隐含的陷阱:许多Java里的图像处理库都不是纯Java的,而是对某些native库的包装(例如JMagick之于ImageMagick)。这样就不只要关注纯Java的部分,还得关注Java与native交互(JNI)的部分。
如果题主问题中的Image类有finalizer(void finalize()方法)并且该finalizer能正确释放native部分的资源的话,那这个代码就没问题;
反之,如果这个Image类有特别说明需要显式调用释放资源的方法去释放native资源的话,那题主的代码就会泄漏native资源。这方面请参考另①个问题的回答:
为什么Java有GC还需要自己来关闭某些资源? - RednaxelaFX 的回答
Java使用JNI调用C写的库时,使用malloc分配的内存是由谁来管理? - RednaxelaFX 的回答
于是题主问的Image类是这个么?
Image (MID Profile)\", \"extras\": \"\", \"created_time\": ①④④⑦③⓪⑧①①⑥ · \"type\": \"answer
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息