JAVA jar命令(一)-jar打包class文件
jar包本质上是将所有class文件、资源文件压缩打成一个包(也可以选择不压缩),可选择在jar包中生成META-INF/MANIFEST.MF文件,MANIFEST.MF是清单文件,里面可以记录主类、classpath等信息,供虚拟机使用。
接下来的一段时间里,我们将以以下路径学习jar命令和清单文件的相关知识
jar打包class文件
带包class文件jar打包
清单文件的使用
在这篇文章里我们将使用简单的java程序来熟悉jar命令的使用,因为是出于熟练使用jar的目的,下面的操作中可能会啰里啰嗦、重复使用jar命令,以下是本片文章的目录,精简版直接看 jar命令的选项
一 jar命令的选项
用法
选项
本节中使用到的命令
二 只有一个class文件的可执行jar的实现
方法一将Mainjar全部解压修改MANIFESTMF文件后再重新打包
方法二生成jar包的时候为其指定清单文件
方法三为jar包指定清单文件
方法四为jar更新文件文件是清单文件
三 多个class的打包
一. jar命令的选项
用法:
大括号中的选项是必选的,中括号里选项是可选的,jar-file是jar文件;manifest-file是清单文件,即jar包中的META-INF/MANIFEST.MF文件
jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
1
选项:
-c (create)创建新档案
-t 列出档案目录
-x 从档案中提取指定的 (或所有) 文件
-u (update)更新现有档案
-v 在标准输出中生成详细输出
-f 指定档案文件名
-m 包含指定清单文件中的清单信息
-n 创建新档案后执行 Pack200 规范化
-e 为捆绑到可执行 jar 文件的独立应用程序
指定应用程序入口点
-0 仅存储; 不使用任何 ZIP 压缩
-P 保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
-M 不创建条目的清单文件
-i 为指定的 jar 文件生成索引信息
-C 更改为指定的目录并包含以下文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
本节中使用到的命令
jar uf xx.jar [file … | path]是需要注意的,它在更新完jar文件后会生成新的清单文件,这一点在本篇文章的 “方法4:为jar更新文件,文件是清单文件” 中有实例说明
jar cf xx.jar [file ... | path] 将file等文件或path目录打包成xx.jar
jar cvf xx.jar [file ... | path] 同上,显示详细信息
jar cmf manifest-file xx.jar [file ... | path] 将file等文件或path目录打包到xx.jar,并制定它的清单文件
jar cMf xx.jar [file ... | path] 将file等文件或path目录打包到xx.jar,包中不生成清单文件
jar uf xx.jar [file ... | path] 将file等文件或目录更新到xx.jar,务必注意!!!这个更新会重新生成清单文件
jar uMf xx.jar [file ... | path] 同上,但不会生成清单文件
jar umf manifest-file xx.jar {file ... | path} 将file等文件或path目录更新到xx.jar
jar tf xx.jar 列出xx.jar中所有文件
jar xf xx.jar 把xx.jar中所有文件提取到当前目录
jar xf xx.jar {file ...} 把xx.jar中file等文件提取到当前目录
1
2
3
4
5
6
7
8
9
10
二. 只有一个class文件的可执行jar的实现
首先创建一个jarDemo文件夹,里面放置我们的测试类
mkdir jarDemo
cd jarDemo
touch Main.java
1
2
3
在Main.java里面添加我们的hello world代码,并javac编译
public class Main{
public static void main(String ... args){
System.out.println("hello world");
}
}
1
2
3
4
5
javac Main.java
1
然后将生成的Main.class打包,c选项是创建一个新的jar包,f是指定jar包的名字
jar cf Main.jar Main.class
1
如果附加使用v选项,则会列出详细的打包信息
jar cvf Main.jar Main.class
1
我们可以通过t选项来查看生成的jar中的文件,输出的内容也就是包目录和包文件,可以看到是默认生成MANIFEST.MF文件的
jar tf Main.jar
输出:
META-INF/
META-INF/MANIFEST.MF
Main.class
1
2
3
4
5
6
当然我们也可以通过M选项不生成MANIFEST.MF文件,可以看到包中只有Main.class一个文件
rm Main.jar
jar cMf Main.jar Main.class
jar tf Main.jar
输出:
Main.class
1
2
3
4
5
6
虽然我们已经将Main.class打包了,并且Main.class有main(String … args)入口方法,可是这个jar还是不能执行,因为虚拟机并不知道这个包中的哪个class中是有main方法的
java -jar Main.jar
输出:
Main.jar中没有主清单属性
1
2
3
4
下面还是恢复到有MANIFEST.MF文件的Main.jar包,我们要将他解压,在MANIFEST.MF中添加主类属性
解压jar包的方法有很多种,我们解压的目的是为了查看默认生成的MANIFEST.MF文件,并做修改,最后生成一个可执行的jar包,因为我们的目的是出于熟练使用jar命名,下面我们将使用多个方法实现这个目标
方法一:将Main.jar全部解压,修改MANIFEST.MF文件后再重新打包
因为jar解压命令只能解压到当前目录,这样会造成文件混乱,我们新建一个uncompress文件夹,将Main.jar拷贝到这个文件夹后再解压,可以看到,jar包中所有文件,x选项是提出全部或指定文件,这个例子里是提出全部文件,实际中可以用f选项提出指定文件,比如 >> jar xf Main.jar META-INF/MANIFEST.MF
mkdir uncompress
cp Main.jar uncompress
cd uncompress
jar xf Main.jar
ls -RF
输出:
META-INF/ Main.class Main.jar
./META-INF:
MANIFEST.MF
1
2
3
4
5
6
7
8
9
10
11
打开META-INF/MANIFEST.MF文件,看到默认生成的清单文件很简单,只有两行
Manifest-Version: 1.0
Created-By: 1.8.0_101 (Oracle Corporation)
1
2
添加上添加上主类属性,注意冒号后面一定要留一个空格,最后一定要多留一个换行符
Manifest-Version: 1.0
Created-By: 1.8.0_101 (Oracle Corporation)
Main-Class: Main
1
2
3
然后使用再将uncompress中所有目录、文件全部打包,注意先将原来的Main.jar删除,最后就可以运行这个新的有主类属性的Main.jar啦
rm Main.jar
jar cMf Main.jar .
java -jar Main.jar
输出:
hello world
1
2
3
4
5
6
注意上面这个jar命令使用的M选项是不生成清单,因为原本uncompress目录里就有,如果还是使用jar cf命令,生成的清单和上面第一次打包生成清单的是一样的,没有Main-Class: Main主类
rm Main.jar
jar cf Main.jar .
java -jar Main.jar
输出:
Main.jar中没有主清单属性
1
2
3
4
5
6
方法二:生成jar包的时候为其指定清单文件
还是那个方法一的uncompress目录,我们把META-INF下的MANIFEST.MF移到uncompress目录下,删除Main.jar,和META-INF目录,让uncompress中只有Main.class和MANIFEST.MF两个文件,MANIFEST.MF是有主类属性的清单文件
mv META-INF/MANIFEST .
rm Main.jar
rm -r META-INF
ls -RF
输出:
MANIFEST.MF Main.class
1
2
3
4
5
6
7
接下了指定清单文件,生成Main.jar,m选项可以指定一个清单文件
jar cmf MANIFEST.MF Main.jar Main.class
java -jar Main.jar
输出:
hello world
1
2
3
4
5
方法三:为jar包指定清单文件
还记得最早那个jardemo目录里的那个清单里没有主类的Main.jar吗,我们为它更新有主类的清单文件
jardemo/uncompress目录下的的MANIFEST.MF是有主类的,我们把它移到jardemo目录下
cd desktop/jardemo
mv uncompress/MANIFEST.MF .
rm -r uncompress
ls -RF
输出:
MANIFEST.MF Main.class Main.jar Main.java
1
2
3
4
5
6
7
使用u选项更新jar包,使用m选项指定清单文件,输出了一些警告信息,因为新的清单文件和Main.jar包中原来的清单信息有两个字段是重名的
jar -umf MANIFEST.MF Main.jar
输出:
三月 13, 2017 10:50:50 下午 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Manifest-Version.
Ensure that the manifest does not have duplicate entries, and
that blank lines separate individual sections in both your
manifest and in the META-INF/MANIFEST.MF entry in the jar file.
三月 13, 2017 10:50:50 下午 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Created-By.
Ensure that the manifest does not have duplicate entries, and
that blank lines separate individual sections in both your
manifest and in the META-INF/MANIFEST.MF entry in the jar file.
1
2
3
4
5
6
7
8
9
10
11
12
13
再运行这个jar
java -jar Main.jar
输出:
hello world
1
2
3
4
方法四:为jar更新文件,文件是清单文件
使用这个方法主要是为了再次熟悉一下u选项和理解包的概念
我们在jardemo目录里删除有主类清单的Main.jar,再次生成最早的MANIFEST.MF中没有主类的Main.jar
jar cf Main.jar Main.class
1
jar包中的MANIFEST.MF里记录了主类,而MANIFEST.MF只是jar包中的一个文件,我们将Main.jar中没有主类的MANIFEST.MF替换为有主类的MANIFEST.MF和方法三是同样的效果,首先要讲有主类的MANIFEST.MF放在合适的路径里面,我们之前看到jar包中的文件是放在META-INF目录里的,使用u来更新jar,注意需要使用M来忽视清单文件
mkdir META-INF
mv MANIFEST.MF META-INF
jar uMf Main.jar META-INF/MANIFEST.MF
java -jar Main.jar
输出:
hello world
1
2
3
4
5
6
7
三. 多个class的打包
上一节中,jarDemo目录中有Main.java和有主类信息的清单文件MANIFEST.MF,我们只保留这两个个文件,其他全部删掉,然后新建一个Say.java文件
ls -RF
输出:
META-INF/ Main.java Say.java
./META-INF:
MANIFEST.MF
1
2
3
4
5
6
7
在新建的Say.java:
public class Say{
public static void say(String str){
System.out.println("This is " + str);
}
}
1
2
3
4
5
修改Main.java文件,让它调用Say类中的Say.say(…)方法
public class Main{
public static void main(String ... args){
System.out.println("hello world");
Say.say("Charles");
}
}
1
2
3
4
5
6
我们编译文件并打包,注意指定一个那个有主类属性的MANIFEST.MF
javac *.java
jar cmf Main.jar META-INF/MANIFEST.MF Main.class Say.class
java -jar Main.jar
输出:
hello world
This is Charles
JAVA jar命令(一)-jar打包class文件的更多相关文章
- 使用 "java -jar"命令启动jar包时报不支持的jdk版本异常
在使用java -jar 命令启动一个jar包的时候,提示版本不支持: [root@hadoop01 eureka-server-master]# java -jar xuebusi-eureka-s ...
- 转:linux下jar命令与jar包
原文链接:http://blog.chinaunix.net/uid-692788-id-2681136.htmlJAR包是Java中所特有一种压缩文档,其实大家就可以把它理解为.zip包.当然也是有 ...
- Java:Linux上java -jar xxx.jar命令执行jar包时出现Error: Invalid or corrupt jarfile xxx.jar解决方案
背景: 从ftp上上传jar包到linux上,之后在linux上通过ftp命令下载jar包文件,开始执行Java-jar,一直提示错误:Error: Invalid or corrupt jarfil ...
- java -jar命令运行jar包时指定外部依赖jar包 linxux or windows
前尘回顾: setup.bat [chenquan@hostuser tartest]$ cat ../setup.sh javac -encoding UTF-8 -Djava.ext.dirs=. ...
- Linux下用jar命令更新jar包文件
jar -uvf SDK_Web_ChartReport.war view/global/header.jsp echo '样式文件替换进包中' 查看jar包中的文件: jar -tvf SDK ...
- Java启动命令与Maven打包设置
一.Java启动命令 java程序的启动方式有三种: 1.java -jar 生成的jar包中,manifest文件定义了Main Class,可使用该命令 java -jar test.jar 2. ...
- 使用jar命令打jar/war包、创建可执行jar包、运行jar包、及批处理脚本编写
jar 命令 jar 是一个jar.exe可执行命令,即可以生成jar文件,也可以生成war文件 使用示例:jar -cvf ../xxx.jar * -c create,创建新的归档文档 ...
- 使用jar 命令生成.jar遇到的问题(绝对路径)
最近学java遇到一个问题:在使用命令行编译jar包的时候 出现了jar包里面的结构是一个电脑的绝对路径(把jar包变成zip格式后看到的) 之所以出现这个问题一个是以为 jar包会自己识别其相对路径 ...
- jar命令打jar包
jar -cvfM0 cloudwarehouse-enter.jar ./BOOT-INF ./META-INF ./org jar -cvfM0 xxl-job-admin.war ./BOOT- ...
- java应用程序利用Exe4j打包exe文件
1. 使用简介: 把java应用程序打成exe文件我们可以借助第三方软件exe4j来完成.Exe4j大家可以在网上下载,下载地址是: http://www.ej-technologies.c ...
随机推荐
- shell 的正则表达式 grep
以上例子的目的在于,正则表达式只能用grep -n 命令中才有作用.在ls中,他的意义是不同的,例如*符号. grep命令的解析 其中,几个特殊的正则表达式: [[:alpha:]] 代表 字母[[: ...
- 笔记63 Spring Boot快速入门(三)
SpringBoot中使用JSP Springboot的默认视图支持是Thymeleaf,但是Thymeleaf还没开始学,熟悉的还是jsp,所以要让Springboot支持 jsp. 一.在pom. ...
- python_django_admin
admin 是Django提供的基于web的管理工具,是系统管理员用于数据的输入,删除和查询的管理工具. 超级管理员在settings中的集成:INSTALLED_APPS=['django.cont ...
- python_异常
异常的概念 程序在运行时,如果 Python 解释器 遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常 程序停止执行并且提示错误信息 这个动作,我们通常称之为:抛出(raise) ...
- 浅谈无线h5开发
最近一直在做h5的项目,对h5开发有了自己的理解.首先h5开发并不是指的html5的开发,而是指无线端的web开发,至于为什么叫h5开发,我觉得一方面是因为html5近几年还是挺受关注,另一方面h5在 ...
- Shiro学习(6)Realm整合
6.1 Realm [2.5 Realm]及[3.5 Authorizer]部分都已经详细介绍过Realm了,接下来再来看一下一般真实环境下的Realm如何实现. 1.定义实体及关系 即用户-角色之间 ...
- 【Flutter学习】基本组件之基本按钮组件
一,概述 由于Flutter是跨平台的,所以有适用于Android和iOS的两种风格的组件.一套是Google极力推崇的Material,一套是iOS的Cupertino风格的组件.无论哪种风格,都是 ...
- 基础(一):SCSI硬盘与IDE硬盘有什么区别
硬盘接口是硬盘与主机系统间的连接部件,作用是在硬盘缓存和主机内存之间传输数据.不同的硬盘接口决定着硬盘与计算机之间的连接速度,在整个系统中,硬盘接口的优劣直接影响着程序运行快慢和系统性能好坏.从整体的 ...
- Delphi实现提取可执行文件内部所有图标
本实例实现的功能是能够从用户选择的可执行文件(后缀名为exe)中提取所有图标并且显示在窗体上. 在窗体中添加TImage 组件.TOpenDialog组件和TButton组件,TImage组件充当显示 ...
- 剑指offer——丑数(c++)
题目描述只包含质因子2.3和5的数称作丑数(UglyNumber).例如6.8都是丑数,但14不是,因为它包含质因子7,习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 思路:1.逐个 ...