使用Maven打包可运行jar和javaagent.jar的区别
简介
javaagent 是 Java1.5 之后引入的新特性,其主要作用是在class被加载之前对其拦截,以插入我们的字节码。
java1.5 之前使用的是JVMTI(jvm tool interface)技术来实现对class的拦截,不过这个是用 C++ 编写的,比如 debug 功能就是用这个技术实现的,有兴趣的自行百度。
jar
常见的jar包分为 可运行jar 和 javaagent.jar ,它们的主要区别如下:
| Executable Jar | Javaagent Jar | |
|---|---|---|
| 入口方法 | main | premain | 
| 打包参数 | Main-Class | Premain-Class | 
| 启动方式 | java -jar xxx.jar | -javaagent:xxx.jar=dddd | 
| 是否可启动 | 是 | 否 | 
入口方法
可运行 jar 包入口方法:
package org.coderead;
public class TestMain {
      // 这个是我们经常写的
      public static void main(String[] args) {
            System.out.println("hello main");
      }
}
javaagent.jar 入口方法:
package org.coderead;
import java.lang.instrument.Instrumentation;
public class TestAgent {
    public static void premain(String arg, Instrumentation instrumentation) {
        System.out.println("javaagent arg=" + arg);
    }
}
MANIFEST.MF 文件方式
Use Your Own Manifest File 这篇官方文档介绍了使用 MANIFEST.MF 打包的方法:
<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>
默认情况下,Maven Archiver为您创建清单文件。有时使用您自己手工制作的清单文件很有用。假设您要使用清单文件 src/main/resources/META-INF/MANIFEST.MF。 通过将 <manifestFile> 配置元素设置为文件的位置来完成此操作。
您自己的清单文件的内容将与Maven Archiver创建的条目合并。 如果您在自己的清单文件中指定一个条目,它将覆盖Maven Archiver创建的值。
注意:与此处的所有示例一样,此配置可以在所有使用Maven Archiver的插件中使用,而不仅仅是本示例中的maven-jar-plugin。
- 打包一个可运行 jar 包 Executable.jar 的 MANIFEST.MF
 
Main-Class: org.coderead.TestMain
注意:
MANIFEST.MF 中需要多留一个空行,也就是输入完成最后一行之后回车
- 打包一个 javaagent 包 javaagent.jar 的 MANIFEST.MF
 
Premain-Class: org.coderead.TestAgent
Maven 项目结构
首先是 可运行jar 的项目结构:

然后是 javaagent.jar 的项目结构:

package 打包 jar

这个对应的命令是mvn package, 打包后会生成 target文件,并且生成 jar 包。
如果在 IDEA 没有找到右边栏,你可能需要点击IDEA左下角的按钮

验证
我在对两个项目执行了 package 之后,把 target\executable-1.0.jar 和 target\javaagent-1.0.jar 移动到同一个文件夹下,比如我在桌面新建了一个 test 文件夹。
然后执行命令
java -javaagent:javaagent-1.0.jar=test -jar executable-1.0.jar
执行结果如下图所示

manifestEntries 标签
还可以使用 <manifestEntries>代替创建 MANIFEST.MF 文件。这样就更加省事了!少创建一个文件!
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.coderead</groupId>
    <artifactId>javaagent</artifactId>
    <version>1.0</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <!--方法一:MANIFEST.MF 配置文件-->
<!--                        <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>-->
                        <!--方法二: pom 指定配置-->
                        <manifestEntries>
                            <Premain-Class>org.coderead.TestAgent</Premain-Class>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
*manifest 标签
借助<manifest> 标签,我们可以指定可运行 jar 的主类。
参考官方文档 中关于<archive>标签讲解。
<archive>
  <addMavenDescriptor/>
  <compress/>
  <forced/>
  <index/>
  <pomPropertiesFile/>
  <manifestFile/>
  <manifest>
    <addClasspath/>
    <addDefaultEntries/>
    <addDefaultImplementationEntries/>
    <addDefaultSpecificationEntries/>
    <addBuildEnvironmentEntries/>
    <addExtensions/>
    <classpathLayoutType/>
    <classpathPrefix/>
    <customClasspathLayout/>
    <mainClass/> <!--The Main-Class manifest entry.-->
    <packageName/>
    <useUniqueVersions/>
  </manifest>
  <manifestEntries>
    <key>value</key>
  </manifestEntries>
  <manifestSections>
    <manifestSection>
      <name/>
      <manifestEntries>
        <key>value</key>
      </manifestEntries>
    <manifestSection/>
  </manifestSections>
</archive>
因此,我们的代码还可以写成
<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <!--指定 Main-Class 来指定可运行 jar 的主类 -->
            <manifest>
              <mainClass>org.coderead.TestMain</mainClass>
            </manifest>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>
总结
我们有两种方式来使用 Maven 打包 javaagent.jar 。
- 一种方式是在 <manifestFile> 标签中指定 META-INF/MANIFEST.MF 文件路径。在文件中填入 javaagent 打包属性。
 - 另一种是在 <manifestEntries> 标签下,直接设置 javaagent 打包属性标签。
 
如果是打包可运行 jar 包,除了前两种方法外,第三种是使用 manifest 标签。
MANIFEST.MF 文件必须要在输入完最后一行配置后输入回车,即留出一行空白行
本文打包使用的插件是 maven-jar-plugin,生成 jar 包的命令是 mvn package
打包 javaagent.jar 必须指定 Premain-Class:org.coderead.TestAgent
使用Maven打包可运行jar和javaagent.jar的区别的更多相关文章
- maven打包 tomcat运行pom配置 或 打成jar包
		
maven打包 tomcat运行pom配置,同时还需要配置org.apache.tomcat.maven插件,这里省略. <groupId>com.company</groupId& ...
 - 关于 maven 打包直接运行的 fat jar (uber jar) 时需要包含本地文件系统第三方 jar 文件的问题
		
关于maven打包fat jar (uber jar) 时需要包含本地文件系统第三方jar文件的问题,今天折腾了一整天.最后还是用了spring boot来做.下面是几篇关于打包的有参考价值的文章,以 ...
 - idea在maven打包时运行Test测试, 导致打包失败, 乱七八糟的错误
		
在maven打包时运行Test测试, 导致打包失败, 乱七八糟的错误 在maven projects中图标toggle'skip Tests' Mode //宏杰帮助 网上案例:https://blo ...
 - spring boot maven打包可运行jar包
		
普通打包之后在程序目录运行,或者编写bat运行时会提示“没有主清单属性”,这是因为并没有找到main()方法,需要我们指明告诉java程序 我bat中的代码 @echo off title mytit ...
 - maven 打包可运行jar包(转)
		
目录 1.前提 2.方法一:使用maven-jar-plugin和maven-dependency-plugin插件打包 3.方法二:使用maven-assembly-plugin插件打包 4.方法三 ...
 - 利用MAVEN打包可运行jar包,包括依赖的第三方包
		
转载自:http://bglmmz.iteye.com/blog/2058914 背景: 另一篇文章说了如何利用IDEA来打包,现在来说说如何利用MAVEN打包 目标:应用本身打成一个jar包,依赖的 ...
 - 【Maven学习】Maven打包生成包含所有依赖的jar包
		
http://blog.csdn.net/u013177446/article/details/54134583 ******************************************* ...
 - maven的几个重要配置文件pom.xml、settings.xml;Maven打包生成包含所有依赖的jar包
		
一个java项目通过maven自动下载依赖时,会涉级读取三个配置文件,分别是项目下的pom.xml 文件 .用户家目录下的.m2/settings.xml 与 maven 全局配置settings.x ...
 - Maven 打包可运行 jar
		
为配合自动化部署hudson,最近研究了如何将eclipse maven工程打包成可运行的jar函数及对应的资源文件. 由于我们工程中包含了多个可运行的任务,在打包成jar时需要分别导出,p ...
 
随机推荐
- MySQL零散知识点(01)
			
内容概要 --- 表字段操作补充(掌握) --- python操作MySQL(掌握) --- 视图(了解) --- 触发器(了解) --- 存储过程(了解) --- 事务(掌握) --- 内置函数(了 ...
 - csp-s模拟测试57(10.2)「天空龙」·「巨神兵」·「太阳神」
			
题目是古埃及神话??? A. 天空龙 傻逼模拟,看来没有滑天下之大稽QAQ,也没有打错快读(大雾...) B. 巨神兵 难度爆增,一脸懵比..... 60分状压: 因为是求有向图,关于有向图好像拓扑用 ...
 - Mysql权限管理以及sql数据备份
			
权限管理和备份 用户管理 可视化管理 SQL命令操作 用户表:msql.user 同样就是对表的操作,就是对这张表的增删改查 -- 创建用户 create user kuangshen identfi ...
 - Qt实现网络聊天室(客户端,服务端)
			
1. 效果演示 客户端 服务器 连接成功之后 2. 预备知识 如果不知道网络编程的可以去看我的上一篇文章C++网络编程 在Qt中,实现网络编程的方式比用C++或C实现要方便简单许多,因为Qt已经替我们 ...
 - TypeScript 在开发应用中的实践总结
			
背景 以前 hybrid app 的移动端开发模式下,H5 和客户端通信的 js sdk 代码使用 js 编写,sdk 方法的说明使用文档输出.对于开发的使用来说,在 IDE 中不能得到友好的参数类型 ...
 - Spring Boot 2.x基础教程:如何扩展XML格式的请求和响应
			
在之前的所有Spring Boot教程中,我们都只提到和用到了针对HTML和JSON格式的请求与响应处理.那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式 ...
 - 『无为则无心』Python基础 — 12、Python运算符详细介绍
			
目录 1.表达式介绍 2.运算符 (1)运算符的分类 (2)算数运算符 (3)赋值运算符 (4)复合赋值运算符 (5)比较运算符 3.逻辑运算符 拓展1:数字之间的逻辑运算 拓展2:Python中逻辑 ...
 - mysql主节点down机后如何恢复操作
			
1 停机维护 (1) 先停止上层应用 (2) 检查backup和slave的中继日志是否已经完成了回放及gtid_executed保持一致 mysql> show slave status\G; ...
 - POJ 1082 Calendar Game 原来这题有个超简单的规律
			
万能的discuss.只需要月份和天数同奇同偶即可,9月30和11月30例外 #include <iostream> #include <cstdio> using names ...
 - java_线程创建的三种方式及区别
			
java中关于线程的创建有三种: (1)通过继承Thread类创建线程. (2)通过实现Runnable接口创建线程. (3)通过Callable 和 Future 接口创建线程. * * * * * ...