[Linux/Java SE]查看JAR包内的类 | JAR 命令 | 反编译

2023-05-17,,

1 查看JAR包内的类

另一个思路: 解压JAR包jar -xf <jarPath>

1-1 单JAR包

-t list table of contents for archive(列出存档内容表)

-f specify archive file name (指定存档文件名)

[root@sdc70 ~]# jar -tf catalina.jar | grep -i "HttpHeaderSecurityFilter"
org/apache/catalina/filters/HttpHeaderSecurityFilter$XFrameOption.class
org/apache/catalina/filters/HttpHeaderSecurityFilter.class

1-2 多JAR包

step1 将需要查找目标类名的JAR包放在同一目录下

step2 解析多JAR包的类及其路径,存放在1个临时文件中

find  <-targetDir-> -name  "*.jar"   -exec   jar  -tf   {} > ./tmpfile-multi-jar-classes.txt \;

step3 从临时文件中查找是否存在目标类

# cat ./tmpfile-multi-jar-classes.txt | grep -i "<keyword>"

[root@sdc70 ~]# cat ./tmpfile-multi-jar-classes.txt | grep -i "HttpHeaderSecurityFilter"
org/apache/catalina/filters/HttpHeaderSecurityFilter$XFrameOption.class
org/apache/catalina/filters/HttpHeaderSecurityFilter.class

2 JAR命令说明

2-1 JAR命令详解

[root@sdc70 ~]# jar --help
Illegal option: -
Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
Options:
-c create new archive
-t list table of contents for archive (列出存档内容表)
-x extract named (or all) files from archive (从归档文件中提取已命名(或全部)文件)
-u update existing archive (更新现有的存档)
-v generate verbose output on standard output (在标准输出上生成详细输出)
-f specify archive file name (指定存档文件名)
-m include manifest information from specified manifest file
-n perform Pack200 normalization after creating a new archive
-e specify application entry point for stand-alone application bundled into an executable jar file (为绑定到可执行jar文件的独立应用程序指定应用程序入口点)
-0 store only; use no ZIP compression
-P preserve leading '/' (absolute path) and ".." (parent directory) components from file names
-M do not create a manifest file for the entries (不为条目创建清单文件)
-i generate index information for the specified jar files (为指定的jar文件生成索引信息)
-C change to the specified directory and include the following file (更改到指定的目录并包含以下文件)
If any file is a directory then it is processed recursively.
The manifest file name, the archive file name and the entry point name are specified in the same order as the 'm', 'f' and 'e' flags.
(如果任何文件是一个目录,那么它将被递归处理。
清单文件名、存档文件名和入口点名称的指定顺序与'm'、'f'和'e'标志相同。) Example 1: to archive two class files into an archive called classes.jar:
jar cvf classes.jar Foo.class Bar.class
Example 2: use an existing manifest file 'mymanifest' and archive all the
files in the foo/ directory into 'classes.jar':
jar cvfm classes.jar mymanifest -C foo/ .

2-2 应用场景

case1: 解压指定的JAR包到当前目录

(注:JAR命令无法指定解压的目标目录)

jar -xf /root/test/catalina.jar

亦可利用WinRAR来实现。

case2: 运行JAR包(/Java类文件)的main方法

[方法1]java -jar ****.jar [args]

适用场景: 1)运行JAR包(需指定具体JAVA类); 2)JAR包内必须指定 META-INF/MANIFEST.MF:Main-Class;

否则,会报此异常: no main manifest attribute, in hello-jar-1.0-SNAPSHOT.jar(hello-jar-1.0-SNAPSHOT.jar中没有主清单属性)

解决此异常/配置META-INF/MANIFEST.MF:Main-Class的方式:

[#1 事后型] 直接编辑已有JAR包进行配置。利用WinRAR解压 JAR包;在其 META-INF/MANIFEST.MF 文件内配置 Main-Class;再利用WinRAR压缩为zip压缩包,重命名为jar即可
[#2 事前型] 普通Maven项目: pom.xml中<build>内配置maven的插件(maven-assembly-plugin),指定 mainClass属性值
[#3 事前型] SpringBoot的Maven项目: pom.xml中<build>内配置maven的插件(spring-boot-maven-plugin)即可

Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: cn.johnnyzen.myBootApplication
java -jar myApp.jar arg_aaa arg_bbb

[方法2]java -classpath ****.jar ****.****.className [args]

适用场景: 1)运行JAR包(无需指定具体JAVA类); 2)JAR包内无需指定 META-INF/MANIFEST.MF:Main-Class

如果没有在JAR包内的META-INF/MANIFEST.MF中指定Main-Class配置时;

或者

如果JAR包中有多个main方法,运行时需指定某个特定的main方法

java -cp myApp.jar com.smbea.dubbo.bin.Console aaa bbb

-cp := -classpath

[方法3]java -Djava.ext.dirs=<多个jar包的目录> com.test.HelloWordMain

(如果用-cp,则需要写每个jar,很麻烦)

【风险】(方法3)

从结果来看,两者(-cp / -Djava.ext.dirs)的区别在于:-Djava.ext.dirs会覆盖JAVA本身的ext设置。

一般情况下程序运行并无差异,因为可以看到ext目录下也就几个jar;

但是如果使用java.security相关类时,就会发现-Djava.ext.dirs会导致library找不到进而报错。

(解决办法暂时想到2种:)

将相关lib复制到新的ext director。验证可行
配置多个director。可以使用冒号分隔(-Djava.ext.dirs=directoryA:directoryB)

case3 : 生成JAR压缩包(打包)

方式1 利用WinRAR对class文件 打JAR包

(详见本文第4章 WinRAR部分)

方式2 jar cvf ./myJarName.jar ./

将当前目录下的所有文件打成jar包,jar包名为main.jar(放在工作目录下)

3 反编译: file.class → file.java

java 反编译 := java decomplier

需求来源

[case1]
当项目已部署时,不确定已部署的war/jar包内某个类文件中是否是预期的内容。
此时,最低成本的做法或许是:直接反编译看看~ 一般,Java Web项目中,class文件在Tomcat的WEB应用此路径下: C:xx/wepapps/xxxApp/WEB-INF/classes/.../Example.class

前置条件

反编译工具 jad.exe

可到该博文处下载: Java 反编译工具几枚(class转java) - CSDN

亦可下载博主提供的: jad158g.win.zip - zip包 解压即安装 (安装包来源于:https://varaneckas.com/jad/)

反编译

step1 切换到jad.exe的目录下
step2 jad -o -r -s java -d src xx/wepapps/xxxApp/WEB-INF/classes/.../Example.class
(执行完毕后,jad的当前目录下会生成1个名为src的子目录,其内会存在反编译后的java文件: Example.java)

jad 命令解析

-o:覆盖旧文件,而且不用提示确认。
-r:重新加载生成包结构。
-s (java):定义输出文件的扩展名。jad为默认扩展名,咱们反编译后,当然是要.java源文件了。
-d:输出文件的目录。src表示反编译后的所有文件都放在src目录下。

4 使用WinRAR: 查看/修改/删除| 解压/生成 JAR压缩包

使用WinRAR 解压/生成 JAR 压缩包

[解压]
step1 选中目标JAR包,右键
step2 (选择WinRAR)解压到当前目录 [生成/压缩]
step1 选中待压缩的目录(一般含:com / META-INF 2个目录),右键
step2 (选择WinRAR)"添加到压缩文件",选择压缩格式为"zip"【必须是zip格式】
step3 重命名zip后缀为jar,即可

使用WinRAR 查看/修改JAR包

step1 打开WinRAR软件
step2 WinRAR>打开压缩文件>(选中目标JAR包)>(查看/修改/删除)

5 反编译神器: Java Decomplier-GUI

下载地址 - Github: http://java-decompiler.github.io/

X 参考与推荐文献

jar 查找多jar包中类的办法 - 博客园
使用 JAR文件 - CSDN
jad(java decomplier) - varaneckas.com
Java 反编译工具几枚(class转java) - CSDN
java的class文件批量反编译成java - CSDN
https://files.cnblogs.com/files/johnnyzen/jad158g.win.zip
https://i.cnblogs.com/files
如何将多个java源文件打包成可执行jar包 - CSDN
maven项目常用的打包方式 (有依赖与无依赖等情况) - CSDN

[Linux/Java SE]查看JAR包内的类 | JAR 命令 | 反编译的相关教程结束。

《[Linux/Java SE]查看JAR包内的类 | JAR 命令 | 反编译.doc》

下载本文的Word格式文档,以方便收藏与打印。