2013-11-24 41 views
5

在C中使用exit(0)不是一种好的做法,如果有替代方法,因为它不会释放资源。但要在Java中使用System.exit(0) - 它在这里如何?在这种情况下可以信任垃圾收集器吗?C中的exit(0)和Java中的System.exit(0)的练习

C语言:

exit(0); 

的Java:

System.exit(0) 
+8

如果你要杀死应用程序,为什么你在乎垃圾回收? –

+1

这是无关紧要的 - 你即将杀死应用程序。这将释放所有的内存。那么为什么要关心垃圾收集? – SevenBits

+0

@Sotirios Delimanolis - 不!在Java中,你可以杀死活动,而不是随机应用程序 – user2991252

回答

2

但使用System.exit(0)在Java中 - 它是如何在这里?在这种情况下可以信任垃圾收集器吗?

当你调用Java中System.exit,垃圾收集器运行不正常。但是,在我听说过的任何JVM中,还有其他东西可以回收分配的所有对象。 (通常在操作系统级别处理。)

GC不运行的事实只有在JVM终止之前依靠对象终结器才能发挥重要作用时才有意义。

假设,如果您的Java应用程序使用JNI(等)调用本机方法,那么这些方法可能会访问可能存在问题的系统资源。但是:

  1. 一般来说操作系统确实采取这样的事情照顾。至少它适用于现代版本的Linux和UNIX,AFAIK。

  2. 无论如何垃圾收集器并不知道这些资源。如果操作系统无法回收它们,那么Java垃圾回收器将无济于事。

如果您确实需要清理由Java程序(通过本机代码)获得这些资源的话,最好的办法是实现本机代码的方法清理,并使用“关闭钩子”运行他们。如果您致电System.exit,关机挂钩将会运行。


1 - 垃圾回收将在JVM退出,如果你以前叫runFinalizersOnExit(true)执行。但是,这是一个已弃用方法。 Oracle的网站解释它是这样的:

问:为什么Runtime.runFinalizersOnExit过时?

答:因为它本质上是不安全的。这可能会导致终结器在活动对象上被调用,而其他线程同时操作这些对象,从而导致不稳定的行为或死锁。如果正在完成对象的类被编码为“防御”这个调用,那么可以防止这个问题,但大多数程序员不会为此辩护。他们假设一个对象在其终结器被调用时已经死亡。

此外,从设置VM全局标志的意义上讲,调用不是“线程安全”的。这迫使每个课程都带有一个终结者来抵御活体对象的终结!

总之,这是一个危险的做法,也不会直接与实物资源的是,OP担心处理。

+0

一般而言,它的确如此,但是,除非您特别努力清理它们,否则System V IPC对象通常会在进程终止后保留。在我正在调试/修复内核时,当我正在对内核进行编程的程序连续多次转储时,我已经达到了共享内存段上的Linux内核限制。消息队列和信号量也会发生同样的情况。请参阅Linux上的ipcs和ipcrm手册页。 – George

+1

_“当您在Java中调用'System.exit'时,垃圾收集器不会运行。”_ - 这在Android中可能是错误的。从[文档](http://developer.android.com/reference/java/lang/Runtime.html#exit%28int%29):_“如果runFinalizersOnExit(boolean)先前已用真实参数调用,则**所有对象将被正确垃圾收集**并最终确定。“_(强调已添加) –

+0

@TedHopp - 在Java SE(至少)该方法已被弃用。不过,我已将这些信息添加为脚注。 –

1

想想这样。在C语言中,您将源代码构建为二进制文件,该文件将自行执行,只符合逻辑编程规则和操作系统设置的规则。然而操作系统并没有为你管理你的内存。它处理事件并向硬件发送信息,告诉它如何运行,没有什么比这更重要。在java中,所有的代码都被编译成java自己的字节码。在执行时,它实际上并不随时与OS进行通信。设计用于运行该字节码的虚拟机是什么话。当你调用System.exit(0)时,你告诉虚拟机你正在运行的应用程序正在停止,从那里机器处理IT'S OWN MEMORY,它恰好包含了你没有通过垃圾收集器,但只有当虚拟机退出时也是如此。希望有所帮助