【JDK命令行 一】手动编译Java源码与执行字节码命令合集(含外部依赖引用)

记录常见的使用javac手动编译Java源码和java手动执行字节码的命令,一方面用于应对 Maven 和 Gradle 暂时无法使用的情况,临时生成class文件(使用自己的jar包);另一方面了解下构建工具做了哪些工作。

作者水平有限,行文中如有错误,希望评论告知,自当尽快修复。

一、编译源码 1. javac 命令

编译Java源码都是使用 javac 命令完成的,其语法如下:

javac [ options ] [ sourcefiles ] [ classes] [ @argfiles ]

options:选项参数,比如-cp,-d

sourcefiles:java源文件,多个文件以空格分开

classes:用来处理处理注解

@argfiles,就是包含 option 或 java 文件列表的文件路径,用@符号开头,就像上面的@javaOptions.txt和@javaFiles.txt

2. 编译仅使用 JDK 类库源码 javac sourcefiles

示例:

Main.java

public class Main { public static void main(String[] args) { System.out.println("Hello World"); } }

编译Main.java

javac Main.java 3. 指定文字编码

默认将使用平台的字符集,如Windows是GBK。为了防止乱码一般指定为 utf-8

javac -encoding encoding sourcefiles

示例:

#指定utf-8编码编译 javac -encoding utf-8 Main.java 4. 指定输出字节码路径

class文件将输出到指定路径下,如果有package,也会一并在指定路径下创建

javac -d path sourcefiles

示例:

#生成字节码到classes目录中 javac -d classes Main.java

注意:指定的目录需要提前创建

5. 指定classpath

指定JVM查找用户类文件、注解解释器和源文件的目录,即字节码、源码等的查找位置。

classpath确定流程:先从环境变量 CLASSPATH 中获取,当用户指定classpath时将覆盖环境变量,如果没有环境变量且未用户设定,将以执行javac的路径向下查找。

#有以下两种写法,二者等效 javac -cp path sourcefiles javac -classpath path sourcefiles #path可以使用通配符*来匹配目录下一级jar包或class文件,比如下列写法 #javac -cp "libs/*" sourcefiles

示例:

引用 FastJson 的Main.java

import com.alibaba.fastjson.JSONObject; public class Main { public static void main(String[] args) { JSONObject json = new JSONObject(); json.put("hello", "world"); System.out.println(json.toJSONString()); } }

编译Main.java,fastjson的jar与Main.java同级目录,直接写jar包作为classpath仅适用于单个jar包引用时

javac -cp fastjson-1.2.73.jar Main.java javac -classpath fastjson-1.2.73.jar Main.java

当设置需要设置多个目录作为classpath时,在不同平台的写法不大一样

Linux/Unix平台

javac -cp "path1/*:path2/*" sourcefiles javac -classpath "path1/*:path2/*" sourcefiles

Windows平台

javac -cp "path1\*;path2\*" sourcefiles javac -classpath "path1\*;path2\*" sourcefiles

不同点仅在于多个目录间使用 : 还是 ; 作为路径分割符、目录分割符是 / 还是 \

6. 指定外部目录

指定外部目录,javac 在编译字节码时将会从下列目录中读取字节码或Jar包,完成编译。

#有以下两种写法,二者等效 javac -extdirs directories sourcefiles -Djava.ext.dirs=directories sourcefiles

示例:

编写Main.java引用多个jar包,指定外部目录编译

import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.StringUtils; public class Main { public static void main(String[] args) { JSONObject json = new JSONObject(); json.put("hello", "world"); System.out.println(json.toJSONString()); System.out.println(StringUtils.equals("1", "1")); } }

fastjson 与 commons.lang3 处于同目录 libs 时,编译命令:

javac -extdirs libs Main.java javac -Djava.ext.dirs=libs Main.java 7. 带package源码编译

Java使用目录作为package定位字节码,减少了重名问题,编译方式是类似的,可使用通配符来匹配待编译的 .java 文件

#src目录下一级目录查找java源码文件编译 javac src/*.java #使用以上方式可能会少编译一些深层次目录下的源码,推荐使用操作系统的命令来查找 #Linux平台 javac $(find src -name "*.java") #Windows平台 where -r src *.java #收集源文件列表 javac <源文件列表> #手动拼接源文件路径,多个源文件以空格分开,如 javac package/A.java package/B.java

此种方式编译少量源文件还可以,源文件过长就会出现命令参数过长报错,可以参考下面章节中的 使用参数文件简化命令 解决此问题

8. 编译有依赖关系的源码

两种方法:

按顺序编译分别编译(编译被依赖,再编译依赖)

由 javac 自动编译(将要编译的源文件列表全部给到 javac 命令后,顺序无所谓)

示例:

PrintService.java

public class PrintService { public void print(String msg){ System.out.println(msg); } }

Main.java

public class Main { public static void main(String[] args) { PrintService printService = new PrintService(); printService.print("Hello World!"); } }

1.按顺序编译:

javac PrintService.java javac Main.java

2.自动编译

javac Main.java PrintService.java 9. 使用参数文件简化命令

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfzsz.html