javac编译java后缀编成class,打包成jar-

前言全局说明

测试环境:
Windows 11
JAVA 1.8.0_301

示例,源码本站下载:java_test_build_jar.zip (约3.81KB)


一、编译独立.java后缀文件

1.1.1 编译单个.java后缀文件

此java文件,没有依赖外部任何jar包。
文件名:test_print.java

public class test_print {
    public static void main(String[] args) {
        if (args.length == 1) {
            System.out.println("[ INFO ]User args:" + args[0]);
        } else {
            System.out.println("[ INFO ] no args!!!");
        }
    }
}

注意:在网页内容复制到.java文件里时,中文可能会导致编译报错,删除或手动输入中文内容即可。

1.1.2 编译命令:

javac test_print.java

编译出 .class 文件

image

1.1.3 运行命令:

java test_print

image



1.2.1 包里的.java后缀文件

文件名:test_print.java

package com;

public class test_print {
    public static void main(String[] args) {
        if (args.length == 1) {
            System.out.println("[ INFO ]User args:" + args[0]);
        } else {
            System.out.println("[ INFO ] no args!!!");
        }
    }
}

java的包概念,在系统里就是文件夹。
假设:java_test 是某个项目文件夹。
在 java_test 文件夹下,新建 com 文件夹,把 test_print.java 放到 com 文件夹里。

资源管理器,显示目录结构::
image

tree命令,显示目录结构:
image

1.2.2 编译命令:

javac com\test_print.java

image

1.2.3 运行命令:

java -cp .;com test_print

-cp 给解释器指定到哪里找到你的.class文件
这里 -cp .;com/ 指定了当前目录.和子目录 com 作为类(包)路径。
-cp <目录和 zip/jar 文件的类搜索路径>
注意: Windows系统使用分号 ; 作为路径分隔符,而在Linux或Mac系统中使用冒号 :

image


二、jar参数说明

用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
选项:
    -c  创建新档案
    -t  列出档案目录
    -x  从档案中提取指定的 (或所有) 文件
    -u  更新现有档案
    -v  在标准输出中生成详细输出
    -f  指定档案文件名
    -m  包含指定清单文件中的清单信息
    -n  创建新档案后执行 Pack200 规范化
    -e  为捆绑到可执行 jar 文件的独立应用程序
        指定应用程序入口点
    -0  仅存储; 不使用任何 ZIP 压缩
    -P  保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
    -M  不创建条目的清单文件
    -i  为指定的 jar 文件生成索引信息
    -C  更改为指定的目录并包含以下文件
如果任何文件为目录, 则对其进行递归处理。
清单文件名, 档案文件名和入口点名称的指定顺序
与 'm', 'f' 和 'e' 标记的指定顺序相同。

示例 1: 将两个类文件归档到一个名为 classes.jar 的档案中:
       jar cvf classes.jar Foo.class Bar.class
示例 2: 使用现有的清单文件 'mymanifest' 并
           将 foo/ 目录中的所有文件归档到 'classes.jar' 中:
       jar cvfm classes.jar mymanifest -C foo/ .

-C 指定了要添加到jar中内容所在目录和内容(这里是所有内容)
-C compiled/ . compiled,指定要添加文件的目录。后面的.代表添加目录下所有东西


三、jar 打包

3.1 使用清单文件,打包单个文件

3.1.1 源码文件

创建 MANIFEST.MF 清单文件
文件名:MANIFEST.MF

Manifest-Version: 1.0
Created-By: 1.8.0_301 (Oracle Corporation)
Main-Class: test_print

注意:

  1. MANIFEST.MF 清单文件, 最后一行一定要有空行
  2. Manifest-Version 和 Created-By 不写,系统会自动生成
  3. MANIFEST.MF 清单文件名可以是任意文件名和后缀,也可以没有后缀

文件名:test_print.java

public class test_print {
    public static void main(String[] args) {
        if (args.length == 1) {
            System.out.println("[ INFO ]User args:" + args[0]);
        } else {
            System.out.println("[ INFO ] no args!!!");
        }
    }
}
3.1.3 编译
javac test_print.java
3.1.2 打包:
jar -cvfm my.jar MANIFEST.MF test_print.class

只写 -cf 不指定 清单文件,打包
image

3.1.4 运行jar包:
java -jar my.jar
java -jar my.jar 你好

image

3.1.5 jar 目录结构

image

image



3.2 指定目录打包

3.2.1 源码文件

创建 MANIFEST.MF 清单文件
文件名:MANIFEST.MF

Main-Class: com.test_print

文件名:test_print.java

package com;
public class test_print {
    public static void main(String[] args) {
        if (args.length == 1) {
            System.out.println("[ INFO ]User args:" + args[0]);
        } else {
            System.out.println("[ INFO ] no args!!!");
        }
    }
}
3.2.2 编译
javac com\test_print.java
3.2.3 执行打包:

示例 1: 将当前目录下面的所有文件归档到一个名为 my.jar 的档案中:

jar cvfm my.jar MANIFEST.MF com\

另:jar 不只是打包 class 文件,还可以将其他jar文件也打包了

3.2.4 运行jar包&效果:

(效果同 3.1.4)

3.2.5 jar 目录结构

image

image



3.3 用.方式打包

3.3.1 源码文件

文件名:MANIFEST.MF
(同3.1.1)
文件名:test_print.java
(同1.1.1)

3.3.2 编译
cd com\
javac test_print.java
3.3.3 执行打包:

使用现有的清单文件 'MANIFEST.MF' 并将 com/ 目录下的所有文件归档到 'my.jar' 中。

jar -cvfm ..\my.jar ..\MANIFEST.MF .

注意:这次执行时,要进入到 D:\java_test\com 目录下

3.3.4 运行jar包:

(效果同 3.1.4)

3.3.5 jar 目录结构

image

image



3.4 用.方式打包

3.4.1 源码文件

文件名:MANIFEST.MF
(同3.1.1)
文件名:test_print.java
(同1.1.1)

3.4.2 编译
javac test_print.java
3.4.3 执行打包:

使用现有的清单文件 'MANIFEST.MF' 并将 com/ 目录下的所有文件归档到 'my.jar' 中。

jar cvfm my.jar MANIFEST.MF -C com/ .
3.4.4 运行jar包:

(效果同 3.1.4)

3.4.5 jar 目录结构

image

image



3.5 用-cp 引入依赖包编译

-cp指明了.java文件里import的类的位置

3.5.1 源码文件

(略)

3.5.2 编译
javac -cp lib\jsch-0.1.54.jar  test_print.java
3.5.3 执行打包:

(略)

3.5.4 运行jar包:

(略)

3.5.5 jar 目录结构

(略)



3.6 用 uvf 更新 jar 包

3.6.1 源码文件

(略)

3.6.2 编译
jar -uvf my.jar com/
3.6.3 执行打包:

(略)

3.6.4 运行jar包:

(略)

3.6.5 jar 目录结构

(略)



3.7 用 -e 参数,指定程序的入口类

用-e参数,就不用写 MANIFEST.MF 清单文件

3.7.1 源码文件

(略)

3.7.2 编译
jar cfe my.jar test_print test_print.class
3.7.3 执行打包:

(略)

3.7.4 运行jar包:

(略)

3.7.5 jar 目录结构

(略)






四、错误:

4.1 "jar中没有主清单属性"t

4.1.1 原因
jar文件的Manifest.mf文件中缺少主类声明引起的。
在Java程序中,主类是程序的入口点,当其他类引用主类时,
JVM(Java虚拟机)可以找到并执行主类中的main方法。
如果jar文件的Manifest.mf文件中没有声明主类,
那么其他类就无法正确引用主类,从而导致程序无法运行。
4.1.2 解决方法:(百度AI)
1. 使用jar命令或者jar工具打开jar文件。
2. 找到或者创建一个名为Manifest.mf的文件。
3. 在Manifest.mf文件中添加以下内容:
  Main-Class: YourMainClassName
  将"YourMainClassName"替换为你的主类的全名,包括包名。

4. 保存并关闭Manifest.mf文件。
5. 使用jar命令或者jar工具重新打包jar文件。

4.2 "错误: 找不到或无法加载主类 test_print"

4.2.1 原因
1.源码里缺少 package com; 指定包路径。
2.运行时没有指定包路径
4.1.2 解决方法:(百度AI)
1.源码里缺少 package com; 指定包路径。(详见1.2.1源码)
2.(详见 1.1.3 命令)


免责声明:本号所涉及内容仅供安全研究与教学使用,如出现其他风险,后果自负。




参考、来源:
https://blog.csdn.net/xiamaocheng/article/details/129229336 (-cp 即 -classpath 指定 jar 路径)
https://blog.51cto.com/u_16099298/6473404 (-cp 参数后面是类路径,是指定给解释器到哪里找到你的.class文件, )
https://blog.csdn.net/lvjingWn/article/details/73605638 (-cp 指明了.java文件里import的类的位置)
https://blog.51cto.com/u_39029/6504810 (-cp 或 -classpath 指定 jar 路径)
https://blog.csdn.net/weixin_48033662/article/details/134311219 (MANIFEST.MF文件,最后一行必须是空行)
https://blog.51cto.com/u_16213440/7117526 (-e参数用于指定程序的入口类为)
https://blog.csdn.net/tiansyun/article/details/137785780 (-C compiled/ .)



posted @ 2024-04-29 11:22  悟透  阅读(1471)  评论(0编辑  收藏  举报