在日常写 Java 程序的工作中,运行,debug 等等操作,本质上都是在进行命令行操作。我们在 IDE 上点击运行,Java 程序就会运行,实际上 IDE 在背后帮我们进行了命令拼接。
我们可以在 IDEA 中编写一个简单的 Java 程序
1 2 3 4 5 6 7 8 9 10 11
| package zzf;
public class Main { public static void main(String[] args) { System.out.println("Hello World"); } }
|
在 zzf 包下面有个 Main.java 类,里面有个 main 方法输出了 “Hello World”。在 IDEA 中点击了运行按钮之后,控制台会有一串命令行
1
| D:\java\jdk\bin\java.exe -javaagent:D:\software\Idea\ideaIU-2019.2.3.win\lib\idea_rt.jar=56956:D:\software\Idea\ideaIU-2019.2.3.win\bin -Dfile.encoding=UTF-8 -classpath D:\Java\jdk\jre\lib\charsets.jar;D:\Java\jdk\jre\lib\deploy.jar;D:\Java\jdk\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk\jre\lib\ext\cldrdata.jar;D:\Java\jdk\jre\lib\ext\dnsns.jar;D:\Java\jdk\jre\lib\ext\jaccess.jar;D:\Java\jdk\jre\lib\ext\jfxrt.jar;D:\Java\jdk\jre\lib\ext\localedata.jar;D:\Java\jdk\jre\lib\ext\nashorn.jar;D:\Java\jdk\jre\lib\ext\sunec.jar;D:\Java\jdk\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk\jre\lib\ext\sunmscapi.jar;D:\Java\jdk\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk\jre\lib\ext\zipfs.jar;D:\Java\jdk\jre\lib\javaws.jar;D:\Java\jdk\jre\lib\jce.jar;D:\Java\jdk\jre\lib\jfr.jar;D:\Java\jdk\jre\lib\jfxswt.jar;D:\Java\jdk\jre\lib\jsse.jar;D:\Java\jdk\jre\lib\management-agent.jar;D:\Java\jdk\jre\lib\plugin.jar;D:\Java\jdk\jre\lib\resources.jar;D:\Java\jdk\jre\lib\rt.jar;D:\idea-work\testDemo\out\production\testDemo zzf.Main
|
当我们把该命令复制到 CMD 窗口运行的时候,同样控制台会打印 “Hello World”
Java 执行过程
我们平时写的源代码(.java 文件),需要编译成字节码(.class 文件),然后再给到 jvm 去解释执行。jvm 只认识字节码,多个 class 文件可以打包成 jar 包来执行。
args 参数
我们写 Java 程序,main 方法里面都有一个 args 参数,实际上这个参数是可以从命令行获取的。编写以下程序获取打印 args 参数
1 2 3 4 5
| public class Main { public static void main(String []args){ System.out.println(java.util.Arrays.toString(args)); } }
|
使用如下命令编辑和运行该程序
可以看到使用 java Main
运行时,打印为空字符串,而在后面添加 1 2 3
三个参数时,打印 [1,2,3]
。
java Main 1 2 3
表示,调用 java 这个可执行程序,然后把 Main 1 2 3
这四个参数传递个 java。java 把 Main 这个类名拿出来,并且运行这个类,后面的参数 1 2 3
当做这个类的参数,传递给这个类的 main 方法。
jvm 中的系统属性和环境变量
系统属性和环境变量是完全不同的东西,系统属性只在 jvm 中有效,不像环境变量可以继承属性。
我们可以在代码中使用 System.getenv() 来获取当前环境变量,使用 System.getProperty() 获取系统属性。我们可以编写如下代码(其中 java.version 是 jvm 自带的系统属性)
1 2 3 4 5 6 7 8 9 10 11 12
| public class Main { public static void main(String []args){ System.out.println("args: " +java.util.Arrays.toString(args)); System.out.println("env: " +System.getenv("zzf")); System.out.println("System Property: " +System.getProperty("zzf")); System.out.println("Java version: " +System.getProperty("java.version")); } }
|
我们先使用 export zzf=helo
给当前环境添加环境变量 zzf,值为 hello,然后运行。
可以发现系统属性 zzf 并没有,打印为 null。而由于 jvm 存在系统属性 java.version,所以正确打印出版本号。要传入系统属性给 jvm 我们需要使用 -D 参数,如图所示。
java 代码中的包
假设有如下代码 zzf.java:
1 2 3 4 5 6 7 8
| import org.apache.commons.lang3.StringUtils; public class zzf{ public static void main (String[] args){ System.out.println(StringUtils.isBlank(args[0])); System.out.println(StringUtils.isBlank(args[1])); System.out.println(StringUtils.isBlank(args[2])); } }
|
该代码引用了第三方的包 org.apache.commons.lang3.StringUtils
,当我们使用 javac 编译的时候会报错,找不到这个包。因此,就需要指定这个包的目录,假设 commons-lang3-3.9.jar
文件和 zzf.java 文件在同一目录下,我们就可以使用 -classpath(简写 -cp),指定文件的位置。
1
| javac -cp commons-lang3-3.9.jar zzf.java
|
这样就可以编译通过。但是在运行 java 程序的时候,需要同时指定引用的包的位置,还需要指定 zzf.class 文件位置
1
| java -cp ./commons-lang3-3.9.jar:. zzf 1 2 3
|
该命令指定了第三方包的位置,以及 zzf.class 文件的位置。由于 zzf.class 文件是在当前目录,所以用 “.” 来表示。在 Linux 中多个目录用 “:” 隔开,Windows 使用 “;” 隔开。
总结
回到这个命令行
1
| D:\java\jdk\bin\java.exe -javaagent:D:\software\Idea\ideaIU-2019.2.3.win\lib\idea_rt.jar=56956:D:\software\Idea\ideaIU-2019.2.3.win\bin -Dfile.encoding=UTF-8 -classpath D:\Java\jdk\jre\lib\charsets.jar;D:\Java\jdk\jre\lib\deploy.jar;D:\Java\jdk\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk\jre\lib\ext\cldrdata.jar;D:\Java\jdk\jre\lib\ext\dnsns.jar;D:\Java\jdk\jre\lib\ext\jaccess.jar;D:\Java\jdk\jre\lib\ext\jfxrt.jar;D:\Java\jdk\jre\lib\ext\localedata.jar;D:\Java\jdk\jre\lib\ext\nashorn.jar;D:\Java\jdk\jre\lib\ext\sunec.jar;D:\Java\jdk\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk\jre\lib\ext\sunmscapi.jar;D:\Java\jdk\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk\jre\lib\ext\zipfs.jar;D:\Java\jdk\jre\lib\javaws.jar;D:\Java\jdk\jre\lib\jce.jar;D:\Java\jdk\jre\lib\jfr.jar;D:\Java\jdk\jre\lib\jfxswt.jar;D:\Java\jdk\jre\lib\jsse.jar;D:\Java\jdk\jre\lib\management-agent.jar;D:\Java\jdk\jre\lib\plugin.jar;D:\Java\jdk\jre\lib\resources.jar;D:\Java\jdk\jre\lib\rt.jar;D:\idea-work\testDemo\out\production\testDemo zzf.Main
|
先不管 -javaagent
,从 -Dfile.encoding=UTF-8
给 jvm 设置一个系统属性 file.encoding=UTF-8,然后使用 -classpath
指定引用的包路径,要运行的文件的位置。最后只剩需要执行的文件名称 zzf.Main
。把上述这些都交给 D:\java\jdk\bin\java.exe
该可执行程序执行。