请问大家在java中,System.exit(-1),System.exit(-2),到-4有啥区别呢?谢谢~

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请问大家在java中,System.exit(-1),System.exit(-2),到-4有啥区别呢?谢谢~相关的知识,希望对你有一定的参考价值。

import java.io.*;
//两个命令行参数分别为源文件全名和目标文件名全名:java FileCopy joyful.txt test_1.txt
class FileCopy
public static void main(String [] args)
FileInputStream in;
FileOutputStream out;
if(args.length<2)
System.out.println("Usage: java FileCopy srcfile destfile");
System.exit(-1);

try
in=new FileInputStream(args[0]);
out=new FileOutputStream(args[1]);
copyFile(in,out);

catch(FileNotFoundException e)
System.out.println("File"+args[0]+"not found or permission denied");//没找到或拒绝许可
System.exit(-2);

catch(IOException e)
System.out.println("Error:"+e);
System.exit(-3);



private static void copyFile(FileInputStream in,FileOutputStream out)
int length;
byte buf[]=new byte[1024];
try
while((length=in.read(buf,0,1024))!=-1) out.write(buf,0,length);

catch(IOException e)
System.out.println("Error:"+e);
System.exit(-4);



那个数是退出状态码,运行任何一个程序都会返回一个数,一般0代表正常退出,其他的数代表出现错误而退出,用来在退出后判断有没有出现什么错误,出现了什么错误。现在大多程序都看不到这个数了,用途不是很多。 参考技术A exit
public static void exit(int status)终止当前正在运行的 Java 虚拟机。参数用作状态码;根据惯例,非零的状态码表示异常终止。
该方法调用 Runtime 类中的 exit 方法。该方法永远不会正常返回。

调用 System.exit(n) 实际上等效于调用:

Runtime.getRuntime().exit(n)

参数:
status - 退出状态。
参考技术B exit
public static void exit(int status)终止当前正在运行的 Java 虚拟机。参数用作状态码;根据惯例,非零的状态码表示异常终止。
该方法调用 Runtime 类中的 exit 方法。该方法永远不会正常返回。

调用 System.exit(n) 实际上等效于调用:

Runtime.getRuntime().exit(n)

参数:
status - 退出状态。
System.exit(0); //正常退出
System.exit(-1); //非正常退出
参考技术C System.exit(0); //正常退出
System.exit(-1); //非正常退出

其它的不知道了,呵呵!
参考技术D exit

从JDK源码看System.exit

前言

    在编写的Java程序中有时会遇到用 System.exit 来关闭JVM,其中调用 exit 方法时会包含一个状态参数n,即System.exit(n)。这其实是一个约定值,如果为0则表示正常关闭,而非0则表示非正常关闭。这里我们从JDK源码看下不同状态都是怎么处理的。

System与Runtime

    先看System类的exit方法如下,可以看到它是间接调用了Runtime对象的exit方法。

public static void exit(int status) {
   Runtime.getRuntime().exit(status);
}


    而Runtime的exit方法如下,先使用SecurityManager检查是否有关闭JVM的权限,允许执行则调用Shutdown的exit方法。

public void exit(int status) {
    SecurityManager security = System.getSecurityManager();
   if (security != null) {
        security.checkExit(status);
   }
   Shutdown.exit(status);
}


Shutdown

    进入到Shutdown类的exit方法,Java层面还有自己的状态state,它可能值为RUNNING、HOOKS和FINALIZERS,可以看到里面的主要逻辑是: 
    1. 不管什么状态下,status为非0时不执行任何Finalizer。 
    2. 在RUNNING状态下,状态转成HOOKS,然后先执行sequence方法,再执行halt方法停止JVM。 
    3. 在FINALIZERS状态下,status为非0时直接 就调用halt方法停止JVM了,而status为0时还需要执行所有的finalizer,之后才调用halt方法停止JVM。

static void exit(int status) {
        
boolean runMoreFinalizers = false;
       
synchronized (lock) {
           
if (status != 0)
                runFinalizersOnExit =
false;
           
switch (state) {
               
case RUNNING:       
                state = HOOKS;
                break;
               
case HOOKS:        
                break;
               
case FINALIZERS:
                       
if (status != 0) {
                    halt(status);
                } else {
                    runMoreFinalizers = runFinalizersOnExit;
                }
                break;
         }
       }
       if (runMoreFinalizers) {
            runAllFinalizers();
            halt(status);
       }
       synchronized (Shutdown.class) {
            sequence();
            halt(status);
       }
}

    sequence方法主要是控制钩子和Finalizer执行的顺序,判断状态不为HOOKS则直接返回,然后执行所有的钩子,把state改为FINALIZERS,最后执行所有finalizer。

private static void sequence() {
       
synchronized (lock) {
           
if (state != HOOKS) return;
     }
     runHooks();
     boolean rfoe;
       
synchronized (lock) {
        state = FINALIZERS;
        rfoe = runFinalizersOnExit;
     }
     if (rfoe)
            runAllFinalizers();
}


halt方法

    执行JVM是通过halt方法实现,这时System.exit(n)的状态n继续往下传递,最终是调用了一个本地的halt0方法。

static void halt(int status) {
    
synchronized (haltLock) {
        halt0(status);
   }
}
static native void halt0(int status);

    对应的本地方法如下,主要是调用了JVM_Halt函数,

JNIEXPORT void JNICALL 
Java_java_lang_Shutdown_halt0(JNIEnv *env, jclass ignored, jint code){
    JVM_Halt(code);
}

    继续往下,JVM_Halt函数主要包含了before_exit函数和vm_exit函数,before_exit函数主要做退出前的一些工作,它只会被执行一次,在多个线程情况下只有获取锁的才能执行,其他线程都必须等。

JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code))
before_exit(thread);  
vm_exit(code);
JVM_END

    而vm_exit函数如下,这里code仍然是Java调用System.exit(n)时传递来的,最主要的是vm_direct_exit函数,它先向jvm发出关闭通知,然后再调用exit函数退出,状态值继续往下传,这时的状态值已经传递到操作系统的API。

void vm_exit(int code) {
  
Thread* thread = ThreadLocalStorage::is_initialized() ?
    ThreadLocalStorage::get_thread_slow() : NULL;  
if (thread == NULL) {
    vm_direct_exit(code);
 }
if (VMThread::vm_thread() != NULL) {
    VM_Exit op(code);
    if (thread->is_Java_thread())
      ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
    VMThread::execute(&op); VM Thread.
    vm_direct_exit(code);
} else {
    vm_direct_exit(code);
 }
ShouldNotReachHere();
}
void vm_direct_exit(int code) {
  notify_vm_shutdown();
  os::wait_for_keypress_at_exit();
  ::exit(code);
}



总结

    Java的System.exit(n)的状态码最终是传递到操作系统的API,所以它的含义与操作系统API的含义相关,当然这个过程Java还会有自己的一些机制工作需要处理。可以说目前大多数平台都可以在 main 函数中直接 return退出程序,但某些平台下不能这样处理,所以为了兼容需要使用 exit() 来退出。


以下是广告相关阅读

========广告时间========

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。


=========================

相关阅读:

 
 
volatile足以保证数据同步吗 
谈谈Java基础数据类型 
从JDK源码角度看并发锁的优化 
从JDK源码角度看线程的阻塞和唤醒 
从JDK源码角度看并发竞争的超时 
从JDK源码角度看java并发线程的中断 
从JDK源码角度看Java并发的公平性 
从JDK源码角度看java并发的原子性如何保证 
从JDK源码角度看Byte 
从JDK源码角度看Boolean 
从JDK源码角度看Short


以上是关于请问大家在java中,System.exit(-1),System.exit(-2),到-4有啥区别呢?谢谢~的主要内容,如果未能解决你的问题,请参考以下文章

仅对某些类允许 System.exit

system.exit() 在 Java 中去哪里了?

从JDK源码看System.exit

在 system.exit() 之后线程仍在运行

System.exit()源码分析

java 多线程 System.exit; 是退出当前线程,还是结束整个虚拟机