最近用命令行执行jar包时,碰巧遇到了这个问题,有点感兴趣,查了大量资料之后,简单地写写我自己的总结,以供大家参考。
   首先,我先贴上我主要参考的文章 一个是javapapers.com,另一个是java和 javaw 以及 javaws的区别,第二篇文章是对第一篇的翻译。还有一个是Oracle的官方文档 Contents of JDK
   再说一些东西,虽然java用了一段时间,但是我到昨天才基本明白jdk 和 jre (里面如果谈深了,就说到jvm了。我现在不懂,就不献丑了) 。jre 全称 java runtime environment ,翻译成中文就是java 运行环境,就是说一个你写的java文件要想跑起来,必须得有个jre。那么jdk是什么,jdk全称 java development kit翻译成中文就是java 开发工具箱,你想开发java语言程序就得用jdk。注意,jdk里面包含了jre,而我们今天谈的上面四个.exe文件就在jdk文件里面。

   如下图所示:

java xp 在哪里 javaws.exe_jdk

javac.exe

   javac 叫做java编译器,我们直接写的.java文件必须编译成.class文件才能运行,而javac的工作就是将我们写的.java 文件翻译成.class文件。

java.exe 和 javaw.exe

初步辨别

  这里我先引用 Oracle官方文档的话。

  The java command starts a Java application. It does this by starting the Java Runtime Environment (JRE), loading the specified class, and calling that class’s main() method.

  也就是说,java.exe的工作就是通过启动jre,加载特定的class文件,并调用class的主方法的方式来启动一个java应用。说白了。java.exe就是让编译后的class文件跑起来。
  那么,javaw.exe又是什么?Oracle官方文档是这么说的,

  The javaw command is identical to java, except that with javaw there is no associated console window. Use javaw when you do not want a command prompt window to appear. The javaw launcher will, however, display a dialog box with error information if a launch fails.

  也就是说,javaw.exe基本上就是java.exe ,但是javaw没有一个相关联的控制台,如果你不想用控制台的话,那就可以用javaw。如果javaw启动程序失败的话,就会出一个dialog窗口展示错误信息。
   是不是不懂?那我来解释一下 。
   首先,我们平时的System.out.println(),打印的东西都到了控制台里面,也就是说,控制台是电脑和人交互的一种方式如果我们写的程序需要控制台,那么我们可以采取java.exe来启动应用程序。
  换言之,如果我们不需要使用控制台的时候我们可以用javaw 来启动应用程序。那什么时候,我们不需要用到控制台呢?这种情况多了去了,GUI(图形用户界面)就是常用的交互方式。
   所以到这里,我们基本明白了java.exe 和javaw.exe的区别,但是在实际操作中又有那些不同呢?

实际操作

   为了操作,我写了一个简单的GUI程序,效果如下所示

java xp 在哪里 javaws.exe_jdk_02


  通过点击图中的点我按钮,其效果是:可以将修改按钮的内容为“Hello World”,并在控制台中输出HelloWorld。代码在文末。

  我现在的想法就是用命令行分别用 java 和 javaw来启动程序,通过观察cmd 和 任务管理器查看到底会有什么效果。为了简单我提前将我的项目打包成jar,放在桌面上。

用java来启动我的jar包

  通过java 启动程序之后,我点击按钮,可以发现控制台的确输出了HelloWorld。请留意箭头所示,接下来将与javaw区分

java xp 在哪里 javaws.exe_jar包_03

  那么查看任务管理器,会发现的确出现了java.exe。


java xp 在哪里 javaws.exe_应用程序_04

用javaw来启动我的jar包

  在下面的gif中,请留意我点下命令的那一刹那,cmd标题的不同。

java xp 在哪里 javaws.exe_java_05


  你会发现在我点下命令的一刹那。cmd的标题突然闪了一下,之后,我再点击按钮,发现控制台并不能打印出:Hello World。也就是说,此时的控制台没有与我的应用程序关联起来。

  继续查看任务管理器,会发现的确出现了javaw.exe.

java xp 在哪里 javaws.exe_java xp 在哪里_06

  那么为什么标题会闪一下?查看javapapers,你会发现它会有这么一句话

  We can execute the above GUI application using both java.exe and javaw.exe If we launch using java.exe, the command-line waits for the application response till it closes. When launched using javaw, the application launches and the command line exits immediately and ready for next command.

  java.exe 和 javaw.exe都可以启动GUI程序。java启动GUI程序时,cmd会等待程序的响应,直到程序终止。也就是说,cmd此时是和程序关联起来的。而javaw启动GUI程序.cmd只存在瞬间,然后就等待下一个命令。也就是说,cmd只存在短暂的时间和程序关联起来,这也是为什么标题闪现的原因之后,cmd就没有和程序关联,所以我们点击按钮,不能打印Hello World到控制台里面。
  我个人猜测,javaw.exe内部肯定是调用了某个函数使得cmd 和程序脱离联系,就好像是简单的if else 语句一样,

......
if(applicationLauncher=="javaw.exe"){
    cmd  和 application脱离联系
}else  if(applicationLauncher=="java.exe"){
    cmd  等待 application响应
}
......

javaws.exe

  javaws.exe 是用来启动web分发的java的程序。我自己不熟悉,所以我不多说,想了解更多,可以点击我之前发的参考文章链接。

总结

  1. javac.exe 是编译程序 ,它将.java文件编译成 .class 文件。
  2. java.exe 是java的启动程序,它有一个与它相关的控制台。
  3. javaw.exe 也是java的启动程序,它与java.exe 没有多大差别,只是它没有一个相关的控制台用于交互而已。
  4. javaws.exe 是用来启动web分发的java的程序。

附录

package com.test;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

/**
 * @Author Lord_Bao
 * @Date 2020/3/2 20:23
 * @Version 1.0
 */
public class HelloWorld extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        //primaryStage 初始化
        primaryStage.setWidth(600);
        primaryStage.setHeight(400);
        primaryStage.setTitle("Hello World");
        primaryStage.getIcons().add(new Image("com/image/ooopic_1572334333.png"));


        //添加组件
        AnchorPane ap=new AnchorPane();
        Button btn=new Button("点我");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                btn.setText("Hello World!!!");
                System.out.println("Hello World!");
            }
        });
        ap.getChildren().add(btn);

        AnchorPane.setTopAnchor(btn,170.0);
        AnchorPane.setLeftAnchor(btn,260.0);

        Scene scene =new Scene(ap);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}