我是一个java程序员,平时运行编译,打包和运行程序都是由IDE或Maven来完成,应用上线部署都是由其他人来写Shell或bat启动停止脚本,有一天让我把一个后台应用打包jar在Linxu或Window部署运行我竟然蒙B了,好半天才想起来javac、java和jar命令。
javac
命令的作用是将java文件编译为class文件。
用法:javac
options
:为命令选项。
source files
:为需要编译的java文件或所在的目录,多个java文件或目录用空格分隔。
常用命令选项:
-d
:指定存放生成的class文件路径
-s
:指定需要编译的java文件或所在路径
-encoding
:指定java文件使用的字符编码。一般都会指定utf-8编码,否则输出的中文是乱码。
-cp
:是-classpath的缩写。指定编译依赖的class文件所在的classpath路径、jar、zip。多个路径、jar、zip使用分号(;)分隔。
java
命令用于执行class、jar文件。
用法:
执行类:java [-options] class [args...]
执行jar:java [-options] -jar jarfile [args...]
options
:命令选项。
class
:需要执行的class文件
jarfile
:需要执行的jar文件
args...
:需要给执行的class文件main方法传递的参数,多个参数使用空格分隔。
常用命令选项:
-cp:同javac命令的-cp。
-D<名称>=<值>:设置系统属性
例如:java -Dmy.config.path=xxx.xml
,my.config.path
为系统属性,xxx.xml
为系统属值。在java中通过System.getProperty("my.config.path")
获取系统属性值。
jar
命令用于将编译好的程序打包成jar文件.
用法:·jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
常用命令选项:
-c
创建新档案
-t
列出档案目录
-x
从档案中提取指定的 (或所有) 文件
-u
更新现有档案
-v
在标准输出中生成详细输出
-f
指定档案文件名
-m
包含指定清单文件中的清单信息
-n
创建新档案后执行 Pack200 规范化
-e
为捆绑到可执行 jar 文件的独立应用程序
指定应用程序入口点
-0
仅存储; 不使用任何 ZIP 压缩
-P
保留文件名中的前导 ‘/’ (绝对路径) 和 “…” (父目录) 组件
-M
不创建条目的清单文件
-i
为指定的 jar 文件生成索引信息
-C
更改为指定的目录并包含以下文件
如果任何文件为目录, 则对其进行递归处理。
清单文件名, 档案文件名和入口点名称的指定顺序
与 ‘m’, ‘f’ 和 ‘e’ 标记的指定顺序相同。
示例 1: 将两个类文件归档到一个名为 classes.jar 的档案中:
jar cvf classes.jar Foo.class Bar.class
示例 2: 使用现有的清单文件 ‘mymanifest’ 并 将 foo/ 目录中的所有文件归档到 ‘classes.jar’ 中:
jar cvfm classes.jar mymanifest -C foo/ .
mymanifest是jar的文件清单,每个jar中都会有一个META-INF/MANIFEST.MF
文件,这个就是文件清单。也可以理解为描述jar的配置文件,当我们执行一个jar时,JVM怎么知道依赖的jar去哪里找,执行入口类是哪个,这些信息都是通过配置mymanifest来实现的。
MANIFEST.MF
文件还可以添加许多其他的信息,感兴趣的自行百度。
我们有个myProject
程序,App为程序的启动类,App
类使用slf4j+logbak
输出User
对象的信息。下面展示一下如果使用javac
命令编译和java
命令运行程序。
程序目录结构如下图。
其中class-out
为存放编译后的class文件,libs
存放程序依赖的jar。
第一步:切换到myProject目录下。
第二步:使用javac
编译项目
javac -cp ./libs/slf4j-api-1.7.25.jar;./libs/logback-core-1.2.3.jar;./libs/logback-classic-1.2.3.jar -d ./class-out -encoding utf8 ./src/com/zhangxy/*.java ./src/com/zhangxy/bean/*.java ./src/com/zhangxy/tool/*.java
其中-cp
指定程序依赖的jar;-d
指定class文件的存放目录;-encoding
指定java文件编码。最后指定需要编译的那些目录下的那些java类。
资源文件(如logback.xml
)在编译完之后需要手工copy到编译目录。
编译成功后目录结果:
第三步:使用java
执行App
java -cp ./class-out;./libs/slf4j-api-1.7.25.jar;./libs/logback-core-1.2.3.jar;./libs/logback-classic-1.2.3.jar com.zhangxy.App argA argB
其中-cp
指定程序依赖的jar,注意/class-out也需要添加到-cp
中,因为执行App需要。
如果/libs
目录下的jar
太对,可以使用/libs/*
表示。
App
需要指定完全限定名称(包名+类名), argA
、argB
是给App
的man
方法传递的参数。
运行结果如下:(图中的命令多了个-cp;
,没有什么作用,请忽略)
第一步编写MAINFEST.FM
Manifest-Version: 1.0
Class-Path: class-out libs/slf4j-api-1.7.25.jar libs/logback-core-1.2.3.jar libs/logback-classic-1.2.3.jar
Main-Class: com.zhangxy.App
这里需要注意:1,每个冒号后面都需要有个空格。2,最后要留一个空行。
第二步:打包jar、执行jar
打包jar:
jar cvfm myPrject.jar ./manifest/MANIFEST.MF -C ./class-out/ .
不明白最后的点(.)是什么意思,不加上就报语法错误。
执行jar
java -jar myPrject.jar