开发工具用久了命令行都忘了怎么用了,做个笔记;
先从最简单的例子开始(先装jdk环境,当前我用的jdk11):
一、单个java文件和包结构;
先在电脑E:\Temp\javatest\JavacTest目录创建一个简单的java文件并编写代码;
按住shift右键打开powershell;
将java文件编译成class,输入:javac .\Hello.java
将多个java文件编译的时候可以用@files参数(powershell里@有冲突,标准cmd和linux可以用),files.txt里可以指定多个java文件,多个java文件间空格隔开(每个java用双引号括起来的时候注意反斜杠转义)
运行class文件,输入:java Hello (不写.class)
打成jar包,输入:jar cvf h.jar .\Hello.class
执行jar包,输入:java -jar .\h.jar (运行失败,没有主清单属性)
因为自动生成的jar包里的META-INF文件夹下的MANIFEST.MF文件不完全,用压缩软件打开jar包,编辑MANIFEST.MF文件,添加Main-Class: Hello,改动保存到jar包里;
重新执行jar包
注:MANIFEST.MF文件的格式比较严格,Manifest-Version是MF版本,Created-By通常由编译器生成(也可自定义),Main-Class指定主类(包名.类名完整格式),还有个Class-Path也常用(指定classpath和引用的jar等);
格式上每项“:”后面需要有一个空格,配置中间似乎不可以有空行,每行最多72个字符(应该是包括回车),换行后下一行需要空一个空格,文件最后要空两行(可能是标准,空一行也能运行);
比如写成这样:
是可以运行的。
关于jar命令,jdk11的太长,我查看了一下jdk1.8的说明:
用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
选项:
-c 创建新档案(创建jar包)
-t 列出档案目录(查看jar包内容)
-x 从档案中提取指定的 (或所有) 文件(解压内容)
-u 更新现有档案(将文件压缩到jar包)
-v 在标准输出中生成详细输出
-f 指定档案文件名(指定打成jar包的名字)
-m 包含指定清单文件中的清单信息(指定mf文件)
-n 创建新档案后执行 Pack200 规范化
-e 为捆绑到可执行 jar 文件的独立应用程序
指定应用程序入口点
-0 仅存储; 不使用任何 ZIP 压缩(容量换速度)
-P 保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
-M 不创建条目的清单文件(-m失效,不会创建MANIFEST.MF)
-i 为指定的 jar 文件生成索引信息
-C 更改为指定的目录并包含以下文件(只在c/u参数有效,相当于先cd过去再执行jar,打包该目录下的文件)
如果任何文件为目录, 则对其进行递归处理。
清单文件名, 档案文件名和入口点名称的指定顺序
与 'm', 'f' 和 'e' 标记的指定顺序相同。
避免在jar包里修改MANIFEST.MF文件,打包时指定MANIFEST.MF即可(这个文件可自定义名称比如a.mf或者a.txt、x.abc等等);
先写一个MANIFEST.MF文件:
执行打包命令,指定MF文件:jar cvfm h2.jar .\MANIFEST.MF .\Hello.class (fm位置要跟h2.jar和mf文件对应起来)
执行jar包是可以运行的
PS:jar包其实就是一个有点特殊的压缩文件,跟zip一样,只不过里面包括一些java包的文件夹和class文件,外加一些配置,还有一个META-INF文件夹和下面的MANIFEST.MF文件;
可以手动建立jar包:新建个文件夹,将class文件和包文件夹放进去(我这只有个没包的Hello.class),然后再建个META-INF在里面编写MANIFEST.MF文件,然后打成压缩包,改压缩包后缀名为jar:
将Hello.java修改加上包结构再试:
生成class执行:javac Hello.java
运行class,输入:java com.test.Hello
因为没按包结构放class文件,新建com/test/文件夹,将Hello.class放入,然后就可以执行了:
使用javac的-d参数,直接指定生成的class文件输出目录,包结构会自动生成:javac -d classes .\Hello.java (win环境classes文件夹会自动生成,linux需要先创建classes文件夹)
使用java的-classpath或者-cp参数指定classpath参数,执行:java -cp .\classes\ com.test.Hello (-cp参数有多个的时候用英文的“双引号引起来”,中间用分号隔开)
打成jar包:jar cvfm h.jar .\MANIFEST.MF .\classes\com\test\Hello.class (可以打包,但运行是有问题的)
因为打的jar包默认是执行jar的这个目录:
显然classes不是包路径;
解决方法1:修改mf文件,指定Class-Path;(不推荐)
解决方法2:命令行cd到classes文件夹下,再打包;
解决方法3:使用jar的-C参数指定打包文件,jar cvfm h.jar .\MANIFEST.MF -C .\classes\ com\test\Hello.class 或者 jar cvfm h.jar .\MANIFEST.MF -C .\classes\ .
二、多个java文件和包结构;
编写Hello和Add两个类,Hello类中使用Add类
生成class:javac -d cls .\Hello.java .\A.java
(((此外,javac还有一个-sourcepath参数,可以指定依赖的java文件位置,该依赖文件需要按照包结构放置目录,并且只会编译实际依赖的java文件,其他不会编译,例如:
把Add.java放到ajava\com\add下,并又添加了A.java、B.java、C.java,执行:javac -sourcepath .\ajava\ -d cls .\Hello.java
执行javac后,Add.class也会编译到cls下,其他没用到的ABC不会编译:
)))
执行class并用-cp指定classpath位置:java -cp .\cls\ com.test.Hello
打成jar包:jar cvfm h.jar .\MANIFEST.MF -C .\cls\ com\
单独编译测试,先编译Add.java,再编译Hello.java
先将Add.java编译到addcls文件夹下:javac -d addcls .\Add.java
再编译Hello.java,用-cp指定Add.class所在,执行:javac -cp .\addcls\ -d hellocls .\Hello.java
(跟java命令一样用-cp指定classpath,-cp参数有多个的时候用英文的“双引号引起来”,中间用分号隔开,-d指定生成目录)
测试运行,输入:java -cp ".\addcls\;.\hellocls" com.test.Hello
打包,输入:jar cvfm h.jar .\MANIFEST.MF .\addcls\ .\hellocls\
(当前目录会把addcls和hellocls文件夹也打包,所以修改MF文件的Class-Path指定classpath)
测试执行jar包:java -jar .\h.jar
三、依赖jar包的情况
先准备依赖的jar包,先将Add.java编译打包
编译:javac -d addcls .\Add.java (依赖的jar包需要有包结构)
打包:jar cvfM add.jar -C .\addcls\ . (需要按实际包结构打包,依赖时包里MF的cp指定似乎不起作用)
开始编译Hello.java用-cp指定依赖jar包,执行:javac -cp .\add.jar -d classes .\Hello.java (classes下只包含Hello.class)
测试执行:java -cp ".\classes\;.\add.jar" com.test.Hello
编写MF文件准备打包,指定依赖的add.jar在libs文件夹下:(指定依赖jar包位置是在所打jar包的外部)
将Hello.class打包:jar cvfm h.jar .\MANIFEST.MF -C .\classes\ . (打jar包就是压缩文件,所以跟依赖的jar无关,只要把class文件和MF打包就行)
可以新建个文件夹,将jar包放进去,add.jar按照MF的配置,要放在libs下:
测试执行jar包:
如果要把依赖的jar包也放到要打的jar包里,需要先把依赖的jar包放到classpath目录下解压,然后再一起打包:
把add.jar复制到classes文件夹下,执行解压:
解压后所有的class文件(包括依赖的)就都在classes下了:
然后把依赖的jar包去掉,统一打包就行:
执行jar包,可以运行: