不知大家在写Java程序的时候有没有这种需求: 将引用其他第三方JAR库的项目打包成一个JAR文件执行.也就是说在你打包好的JAR文件里再包括那些你引用的第三方JAR文件,合成一个JAR包,这样仅仅需在Windows下双击,或在Linux终端下输入 java -jar yourjarfile.jar就可以方便执行.在最初一种普遍的做法是在打包的JAR文件里的META-INF/MANIFEST里使用Class-Path选项,像这样:

Manifest-Version: 1.0
Created-By: 1.7.0_06-b24 (Oracle Corporation)
Main-Class: YOUR.MAIN.CLASS.NAME.HERE
Class-Path: lib1.jar lib2.jar lib3.jar

但这样在执行这个JAR包时仍然须要将引用的lib1.jar,lib2.jar,lib3.jar放入你打包的JAR文件文件夹中.即使你将其打包进你的JAR包中,仍不能够独立执行.

曾经这样打包的问题一直困扰着我,难道在Java中就不能像exe打包程序那样一个文件单独跑吗?

直到今天再次遇到这个问题时,GOOGLE了一下找到了一个不错的解决方式.就是使用第三方工具包One-Jar.相应下载地址:http://sourceforge.net/projects/one-jar/

使用One-Jar很的简单.仅仅须要简单的几步,但在使用One-Jar之前须要事先自行将自己的项目使用jar命令打包成JAR包,当中不包含三方JAR包,再进行例如以下操作:

1.创建一个名为"root"的工作文件夹,当中再包括两个名为"main"和"lib"的子文件夹;

2.顾名思意,这里root/main用于存放你自己已经打包好了的JAR文件,并将它改名为main.jar,注意在打包你的class文件时,不要包括不论什么你引用的JAR包.而相应的root/lib才用来存放那些你引用的第三方JAR包.

3.从One-Jar官网中下载最新的One-Jar包.并将它解压放入到root文件夹中,相应的重名文件夹合并.同一时候去掉"src"文件夹.(注意在解包One-Jar时的隐藏文件).

4.再在root文件夹中新建一个名为boot-manifest.mf的文件,其内容例如以下:

Manifest-Version: 1.0
Main-Class: com.simontuffs.onejar.Boot
One-Jar-Main-Class: YOUR.MAIN.CLASS.NAME.HERE

5.最后一步,在命令行下输入cd root进入root文件夹,然后执行java的打包命令例如以下:

jar -cvfm ../你的程序名.jar boot-manifest.mf .

执行后,假设一切顺利,则会在root文件夹的上层文件夹中生成"你的程序名.jar"的文件,这时在windows环境中,你仅仅须要双击这个文件则能够执行启动你的程序.就这种一个文件,很的给力!哈哈

在进行One-Jar的打包时一定要注意它的相应文件夹结构,例如以下给出root文件夹具体的结构说明:

root文件夹
| .version
| one-jar-$project$.jar
| OneJar.class
| boot-manifest.mf # 你新建的boot-manifest.mf
| com/simontuffs/onejar # One-Jar的源文件文件夹
| Boot.class, ...etc.
| doc/one-jar-license.txt # 相应的软件协议
| main/main.jar # 你的程序JAR
| lib/a.jar ...etc. # 你程序依赖的第三方JAR包

假设一切都是依照上面的文件夹结构来的,应该就不会有问题.事实上One-Jar不仅能够单独使用,还能够与Ant与Meavn等Java项目源代码管理软件结合使用,在这里就不细说了(哈哈, 关键是我没有试~),感兴趣能够到http://one-jar.sourceforge.net/index.php?page=getting-started&file=quickstart处查看.

条条道路通罗马,不只One-Jar能够,我还查了一下,还有UberJarShade也具有相同的功能.只只是它俩好像还须要依赖Maven.相应stackoverflow上大神的原话(处出:http://stackoverflow.com/questions/183292/classpath-including-jar-within-a-jar):

If you're trying to create a single jar that contains your application and it's required libraries, there are two ways (that I know of) to do that. The first is One-Jar, which uses a special classloader to allow the nesting of jars. The second is UberJar,
(or Shade), which explodes the included libraries and puts all the classes in the top-level jar.I should also mention that UberJar and Shade are plugins for Maven1 and Maven2 respectively. As mentioned below, you can also use the assembly plugin (which in
reality is much more powerful, but much harder to properly configure).

关于Java启动器为什不能使用Class-Path载入JAR包里面的JAR库,也在stackoverflow上找到了相应的解释说明(出处:http://stackoverflow.com/questions/12357136/reference-jars-inside-a-jar),例如以下:

The Java Launcher$AppClassLoader does not know how to load classes from a Jar inside a Jar with this kind of Class-Path. Trying to use jar:file:jarname.jar!/commons-logging.jar also leads down a dead-end.
This approach will only work if you install (i.e. scatter) the supporting Jar files into the directory where the jarname.jar file is installed.

最后关于One-Jar的原理的一点小小的猜想:我想就是使用Java库中的某个工具类,先事强制载入指定文件夹的JAR包于内存.然后使用反射机制调用META-INF/MANIFEST文件里One-Jar-Main-Class项指定类的main方法,实现程序启动的目地的吧.而详细怎么实现就要好好的研究One-Jar的源代码了~

在JAR中打包使用JAR库的更多相关文章

  1. jar包有嵌套的jar的打包成jar的方法

    1.先写一个类,将其打包成jar包. 代码如下: package com.wjy.jar; public class GetUserName { public String getUserName() ...

  2. eclipse导出jar(java打包导出jar)

    有时候需要将j2se工程导出,这样可以在别处运作,就不必拘泥于开发感觉中才能运行了.具体做法如下:方法一:(工程没有引用外部jar包时,直接导出) 选中工程---->右键,Export...-- ...

  3. iOS中打包.a静态库

    1.新建.a静态库工程 需要选择Static Library静态库工程模板新建工程,如下图: 新建静态库工程 实现需要打包的类,如下图: 实现需要打包的类 2.设置需要暴露的头文件 添加Headers ...

  4. 深入jar包:从jar包中读取资源文件getResourceAsStream

    一.背景 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等). 在单独运行的时候这些简单的处理当然不会有问题.但是,如果我们把代码打成一个jar包以后,即使将资源文件一并打包,这些东西也找不 ...

  5. [Java基础] 深入jar包:从jar包中读取资源文件

    转载: http://hxraid.iteye.com/blog/483115?page=3#comments 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等).在单独运行的时候这些简单的 ...

  6. 深入jar包:从jar包中读取资源文件

    我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等).在单独运行的时候这些简单的处理当然不会有问题.但是,如果我们把代码打成一个jar包以后,即使将资源文件一并打包,这些东西也找不出来了.看看 ...

  7. [学习笔记] 在Eclipse中导出可以直接运行的jar,依赖的jar中的类解压后放在运行jar中

    前文: [学习笔记] 在Eclipse中导出可以直接运行的jar,依赖的jar打在jar包中 使用7z打开压缩包,查看所有依赖的jar都被解压以包名及class的方式存储在了运行jar中,此时jar的 ...

  8. SpringBoot引入第三方jar包或本地jar包的处理方式

    在开发过程中有时会用到maven仓库里没有的jar包或者本地的jar包,这时没办法通过pom直接引入,那么该怎么解决呢 一般有两种方法 第一种是将本地jar包安装在本地maven库 第二种是将本地ja ...

  9. 在Android源码中如何吧so库打包编译进入apk, 集成第三方库(jar和so库)

    集成第三方so和jar包 include $(CLEAR_VARS) #jar包编译            LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=securit ...

随机推荐

  1. KMP中next数组的理解与应用

    理解 1.next数组一直往前走 next数组一直往前走,得到的所有前缀也是当前主串的后缀,当然了,也是当前主串的前缀. 2.周期性字符串 1.周期性字符串$\Leftrightarrow n \,\ ...

  2. 循环实现数组 map 方法

    //循环实现数组 map 方法 const selfMap = function (fn, context) { let arr = Array.prototype.slice.call(this) ...

  3. C 语言指针 5 分钟教程

    指针.引用和取值 什么是指针?什么是内存地址?什么叫做指针的取值?指针是一个存储计算机内存地址的变量.在这份教程里“引用”表示计算机内存地址.从指针指向的内存读取数据称作指针的取值.指针可以指向某些具 ...

  4. C#readonly 关键字与 const 关键字的区别

    1. const 字段只能在该字段的声明中初始化,readonly 字段可以在声明或构造函数中初始化.因此,根据所使用的构造函数,readonly 字段可能具有不同的值. 2. const 字段是编译 ...

  5. Tomcat的配置方法(解压版)

    Tomcat解压版虽然不用安装,但是死难配!!之前刚学的时候很是郁闷了一阵,Jsp倒还好,但是Servlet死活跑不起来.今天就把你给记下来!! 解压到C:/Tomcat 然后再配置环境变量: 添加三 ...

  6. 导入.sql文件入数据库

    1.创建数据库,例如abc create database abc; 2.进入数据库 use abc 3.导入e盘下的ssh.sql文件即可 source e:\ssh.sql; 截图如下:

  7. PHP与MySQL的亲密接触

    PHP与MySQL的亲密接触   此篇文章前,你应该先做好一些准备工作 1.建好一个mysql数据库,记住servername,username,password 三者缺一不可. 2.在数据库创建cr ...

  8. BZOJ 4695 最假女选手 线段树

    题意: 给定一个长度为 N序列,编号从1 到 N.要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x  2.把一个区间[L,R] 里小于x 的数变成x  3.把一个区间[L,R] 里大于x ...

  9. Python使用Flask框架,结合Highchart,自定义导出菜单项目及顺序

    参考链接: https://www.highcharts.com.cn/docs/export-module-overview https://api.hcharts.cn/highcharts#ex ...

  10. C#上位机开发(四)—— SerialAssistant功能完善

    上一篇中我们完成了一个串口助手的雏形,实现了基本发送和接收字符串功能,并将打开/关闭串口进行了异常处理,这篇就来按照流程,逐步将功能完善: 1.构思功能 首先是接收部分,要添加一个“清空接收”的按钮来 ...