`
Josh_Persistence
  • 浏览: 1649990 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

浅谈java 中构建可执行 jar 包的几种方式

阅读更多

概述

      有时候,由于项目的需要,我们会将源码编译后以工具包(即将class打成jar包)的形式对外提供,此时,你的 jar 包不一定要是可执行的,只要能通过编译,能被别的项目以 import 的方式调用就行了。

       但还有的情况是,我们的 jar 包是要可执行的,即能直接在 cmd 下直接通过java -jar的命令运行。

       前者的打包很简单,在 eclipse 中,直接选中要打包的 java 文件和其它资源、依赖文件, export → Java → JAR file 即可。需要注意的是,这种方式导出的 jar 包是不可执行的,比如你执行如下的语句:
java -jar test.jar
java -classpath test.jar com.test_maven.App
      会直接报错:无法找到主类或者找不到 xxx 依赖包/类,这是由于你没有定义 MANIFEST.MF 资源描述文件所致。另一个原因可能是你直接把依赖的 jar 包打进了你最终的 jar,而这种嵌套的依赖 jar 包是不能直接被程序 import 识别的。

 

如何构建可执行Jar包
        

方法1、最简单的还是依赖于 eclipse 的导出功能

export → java → Runnable JAR file,这种形式的导出可以通过 lanuch configuration 指定一个 MainClass,并会自动生成 MANIFEST.MF ,而且会帮你把依赖的 jar 包解压出来,一并打进最终的 jar 包,这样就能被你的代码 import 引用了。

 


 

 

方法2、利用Eclipse的Fat Jar

       上述方法是 eclipse 自带的,此外eclipse 也有个专门的插件叫做 Fat Jar,支持许多定制化的功能,但是这个插件有些缺陷,比如修改源码后如果你不 clean & rebuild project, 它会使用缓存重新打包,这样你的编译代码还是老的,会造成执行错误,而且这样是十分不方便的。用Fat Jar Eclipse Plug-In打包可执行jar文件

 

 

方法3、利用Maven的插件

    

3.1: 基于Maven构建的项目最好的方式:

          将项目所支持的所有类库打在一个包中,而不是只将项目编译打包到一个jar中。这样便可以直接拷贝一个jar去执行了。

 

<plugin>
			    <artifactId>maven-assembly-plugin</artifactId>
			    <configuration>
			        <appendAssemblyId>false</appendAssemblyId>
			        <descriptorRefs>
			            <descriptorRef>jar-with-dependencies</descriptorRef>
			        </descriptorRefs>
			        <archive>
			            <manifest>
			                <mainClass>com.ebay.montage.eventprocessor.collector.CodeRollOutEventDataCollector</mainClass>
			            </manifest>
			        </archive>
			    </configuration>
			    <executions>
			        <execution>
			            <id>make-assembly</id>
			            <phase>package</phase>
			            <goals>
			                <goal>assembly</goal>
			            </goals>
			        </execution>
			    </executions>
			</plugin>

 

使用命令:

mvn assembly:assembly -DskipTests

这里就会在target目录下生成 {project}.jar文件,

直接运行jar文件: Java -jar  {project}.jar

    备注:当然也可以使用mvn clean install -DskipTests 来构建生成jar包。

 

 需要注意的是,这种方式在新版本的Maven或者Spring中很多时候执行jar包会出现类似如下的exception:

 

Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]
 其原因是新版本的Maven中推荐使用shade来替代assembly方式,于是可以使用如下的命令来代替上面的命令以解决Spring NamespaceHandler for XML schema namespace的异常问题

 

 

<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-shade-plugin</artifactId>
     <version>2.1</version>
     <executions>
	<execution>
	     <phase>package</phase>
		<goals>
		<goal>shade</goal>
		</goals>
	      <configuration>
		<transformers>
		  <transformer
	implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
		<resource>META-INF/spring.handlers</resource>
		</transformer>
		<transformer
	implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
		<resource>META-INF/spring.schemas</resource>
	</transformer>
		<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
	<mainClass>com.chuanliu.c11.bootstrap.C11SearcherBootStrap</mainClass>
	</transformer>
	</transformers>

	<filters>
	  <filter>
		<artifact>*:*</artifact>
	        <excludes>
		<exclude>META-INF/*.SF</exclude>
		<exclude>META-INF/*.DSA</exclude>
		<exclude>META-INF/*.RSA</exclude>
		</excludes>
	</filter>
	</filters>
	</configuration>
	</execution>
       </executions>
</plugin>
该命令有几点需要注意:
1、MainClass必须要指定,否则在运行打包生成的Jar包后,会报这样一个错误:“没有主清单属性”
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
	<mainClass>com.chuanliu.c11.bootstrap.C11SearcherBootStrap</mainClass>
	</transformer>
 
2、执行生成的Jar包的时候,有时候还会出现:SecurityException: Invalid signature file digest

 

这是由于在META-INF下会有多余的以SF结尾的文件,用winrar打开jar包并删除META-INF下的SF结尾的文件后,执行就不会出现改问题,但更好的方法就是像上面一样,生成可执行jar包时加入filters命令

<filters>
	  <filter>
		<artifact>*:*</artifact>
	        <excludes>
		<exclude>META-INF/*.SF</exclude>
		<exclude>META-INF/*.DSA</exclude>
		<exclude>META-INF/*.RSA</exclude>
		</excludes>
	</filter>
</filters>

  

 

      3.2: 在 maven 工程中,我们也可以很方便的打包成可执行的 jar 包。默认Maven生成的JAR包只包含了编译生成的.class文件和项目资源文件,而要得到一个可以直接在命令行通过java命令运行的JAR文件,还要满足两个条件:

 

  • JAR包中的/META-INF/MANIFEST.MF元数据文件必须包含Main-Class信息。
  • 项目所有的依赖都必须在Classpath中,其可以通过 MANIFEST.MF 指定或者隐式设置。

 

<plugins>
     <plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<configuration>
	<archive>
	<manifest>
		<addClasspath>true</addClasspath>
		<classpathPrefix>lib/</classpathPrefix>
		<mainClass>com.ebay.montage.eventprocessor.collector.MySpace</mainClass>
	</manifest>
	<manifestEntries>
		<Class-Path>.</Class-Path>
	</manifestEntries>
	</archive>

	finalName>eventprocessor</finalName>
	<!-- <excludes>
		<exclude>**/*.properties</exclude>
		<exclude>**/*.xml</exclude>
	</excludes> -->
	</configuration>
	</plugin>

       <plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-dependency-plugin</artifactId>
		<executions>
		<execution>
			<id>copy-dependencies</id>
			<phase>prepare-package</phase>
			<goals>
			<goal>copy-dependencies</goal>
			</goals>
			<configuration>
			<outputDirectory>${project.build.directory}/lib</outputDirectory>
			<overWriteReleases>false</overWriteReleases>
			<overWriteSnapshots>false</overWriteSnapshots>
			<overWriteIfNewer>true</overWriteIfNewer>
			</configuration>
			</execution>
		</executions>
	</plugin>
    </plugins>

 

使用mvn clean install -DskipTests打jar 包。

 

 

这样打好jar包后就可以使用:java -jar eventprocessor.jar Myspace,

当然了前提是在Myspace中有一个main方法。这样便可直接去执行Myspace中的main方法了。

但是如果要将jar包放到别的机器上去运行的话,需要将targe中的lib下的内容(上面命令中指定)也同样拷贝过去,因为默认情况下:maven只是将项目编译打包到一个jar中,而其它的类库在上面手动的指定被放到了lib中,所以在执行的时候必须要引用才行。

 


 

 

附:如果对Maven感兴趣,如下文章的几个功能有必要了解一下:关于 Apache Maven 您不知道的 5 件事

http://www.ibm.com/developerworks/cn/java/j-5things13/

 

方法4、手动维护:

当然了,如果你不怕麻烦的话,手动打包,自己建立、维护 MANIFEST.MF 文件也是可以的,我没有试过这种方法,具体可以参考如下链接:

http://blog.csdn.net/mango_song/article/details/8531389

http://gushuizerotoone.iteye.com/blog/1757002

2
1
分享到:
评论

相关推荐

    关于执行java命令引入外部jar包方法

    总之,无论是通过修改环境变量还是在命令行中使用`-cp`参数,正确地引入外部JAR包对于构建功能完整的Java应用程序至关重要。掌握这些技巧,可以帮助开发者更高效地管理和利用外部库,提高项目的可维护性和扩展性。

    集成小工具,可执行jar包

    标题中的“集成小工具,可执行jar包”指的是一个包含了一系列工具的Java应用程序,这些工具被封装在一个可执行的JAR(Java Archive)文件中。JAR文件是Java平台特有的打包格式,它允许将多个Java类文件、资源文件...

    你们想要的java jar包全都有

    标签"jar包"直接指明了主要内容,即Java的可执行或库JAR文件。在Java开发中,JAR包扮演着重要角色,它们可以是独立的应用程序(通过主类执行),也可以作为库被其他项目引用。这些JAR文件包含了编译后的字节码,可以...

    java的workbook类的jar包

    在Java中,当你需要与Excel交互时,首先需要创建或加载一个`Workbook`实例。如果你要创建一个新的Excel文件,可以使用`WorkbookFactory.create()`方法,并指定你想要的格式(如`.xlsx`或`.xls`)。如果是要读取已有...

    可执行jar文件.以及执行命令

    可执行JAR(Java Archive)文件是Java编程语言中的一种打包格式,用于集合多个类文件、资源和其他相关文件,形成一个单一的可分发单元。它不仅方便了代码的组织和传输,还允许我们直接运行Java应用程序,无需显式...

    javacv所有jar包-java

    从javacv-platform-1.3.3-bin.zip中抽出来的:javacpp.jar、javacv.jar、javacv-platform.jar、opencv.jar、opencv-android-arm.jar、opencv-android-x86.jar、opencv-linux-armhf.jar 、opencv-linux-ppc64le.jar、...

    java通用jar包

    Java通用jar包是一种在Java开发中广泛使用的可重用代码库,它包含了预编译的类和资源,便于开发者在自己的项目中导入和使用。jar(Java Archive)是Java平台的标准打包格式,允许将多个Java类文件和其他资源文件集合...

    编译运行java带jar包

    在Java编程环境中,有时我们需要将多个类打包成一个可执行的JAR(Java Archive)文件,以便于分发和执行。这个过程涉及到编译Java源代码、创建类路径(classpath)、构建MANIFEST.MF文件以及最终打包成JAR。下面我们...

    对java jar包实现混淆加密

    Java jar包是Java应用程序的可执行格式,它包含编译后的类文件和其他资源。为了保护源代码不被轻易反编译和理解,开发者通常会使用混淆加密技术来增强代码的安全性。本文将深入探讨如何对Java jar包进行混淆加密,...

    java中支持sip协议的jar包

    本话题将详细介绍Java中支持SIP协议的几个关键jar包以及它们的作用。 1. **concurrent.jar**:这个jar包包含了Java并发编程所需的类和接口,如`java.util.concurrent`包下的线程池、同步器和并发集合。在开发SIP...

    Java、Java web开发所需jar包

    Java web 项目中所需要的常用jar包 很全面 是有一天做项目时发现缺少很多jar包 寻找这些jar包几乎花了我一下午的时间 为方便后来人 故寻找下载并整理了一些jar包 希望对读者有所帮助 因为下载包时消耗了我大量积分 ...

    java连接mysql的jar包

    在Java中,我们通常会使用特定的驱动库来实现与MySQL数据库的连接,这个驱动库就是以JAR(Java Archive)文件形式存在的。标题中的"java连接mysql的jdbc jar包"指的就是这样的驱动库。 描述中提到有两个ZIP文件,这...

    Java常用jar包

    在Java中,jar(Java Archive)文件是一种归档格式,它将多个类文件打包在一起,便于分发和使用。对于数据库操作,一些核心的jar包尤其重要。 在Java数据库连接(JDBC)中,主要的jar包包括`mysql-connector-java....

    Java开发JAR包

    Java开发中的JAR(Java Archive)包是一种标准的文件打包格式,主要用于收集多个类文件、相关的元数据和资源文件,以便在Java平台上运行或分发。JAR文件的使用极大地便利了程序的组织、部署和执行,对于Java开发者来...

    java_jar包

    Java中的JAR(Java Archive)包是Java编程语言中用于集合多个类文件、相关的元数据以及资源文件的压缩格式。这种格式便于分发、存储和运行Java应用程序或库。JAR文件通常包含以下组成部分: 1. 类文件:.class文件...

    java-websocket jar包

    Java WebSocket 是一种基于Java语言实现的WebSocket协议库,主要用于实现在Web应用中提供实时的双向通信功能。WebSocket协议是HTML5规范的一部分,它允许客户端和服务器之间建立持久性的连接,从而实现数据的双向推...

    C++调用java jar包测试代码

    标题 "C++调用java jar包测试代码" 描述了一个跨语言交互的场景,其中C++程序通过调用Java编译后的jar包来执行特定功能。这个过程涉及到多个技术点,包括Java的编译和打包,C++的编程以及两者之间的接口调用。 1. *...

Global site tag (gtag.js) - Google Analytics