java launcher_JAR清单类路径不仅适用于Java Application Launcher
java launcher
自从我开始学习Java以来,我几乎已经知道, 清单文件中的Class-Path标头字段为可执行JAR (具有由另一个称为Main-Class
清单指定应用程序起点的 JAR)指定了相对运行时类路径。 一个同事最近碰到一个让我感到惊讶,因为它证明了一个问题JAR文件的清单的Class-Path
条目也影响编译时类路径时包含在类路径中包含JAR在运行javac的 。 这篇文章演示了这种新变化。
Java教程的部署跟踪的“ 将类添加到JAR文件的类路径 ”部分指出:“您指定要包含在applet或应用程序清单文件中的Class-Path
头字段中的Class-Path
。” 该部分还指出:“通过使用清单中的Class-Path
标头,可以避免在调用Java运行应用程序时指定长的-classpath
标志。” 这两个句子从本质上总结了我一直如何想到清单文件中的Class-Path
标头:作为包含的JAR的类路径是通过Java应用程序启动器( java可执行文件)执行的。
事实证明,JAR清单中的Class-Path
条目会影响Java编译器( javac ),就像它会影响Java应用程序启动器( java )一样。 为了演示这一点,我将使用一个简单的接口( PersonIF
),一个实现该接口的简单类( Person
)和一个简单的Main
类,该类使用实现该接口的类。 接下来显示这些的代码清单。
PersonIF.java
public interface PersonIF
{void sayHello();
}
人.java
import static java.lang.System.out;public class Person implements PersonIF
{public void sayHello(){out.println("Hello!");}
}
Main.java
public class Main
{public static void main(final String[] arguments){final Person person = new Person();person.sayHello();}
}
从上面的代码清单可以看出, Main
类依赖于(使用) Person
类,而Person
类依赖于(实现) PersonIF
。 我将把PersonIF.class
文件放在它自己的名为PersonIF.jar
JAR中,并将该JAR存储在(不同的)子目录中。 Person.class
文件将存在于其自己的Person.jar
JAR文件中,并且该JAR文件包括MANIFEST.MF file
,该MANIFEST.MF file
的Class-Path
标头引用了相对子目录中的PersonIF.jar
。
现在,我将尝试仅使用类路径中的当前目录从Main.java
编译Main.class
。 当javac
在单独的子目录中找不到PersonIF.jar
时,我以前曾期望编译会失败。 但是,它不会失败!
这让我感到惊讶。 当我没有明确指定PersonIF.class
(或包含它的JAR)作为通过-cp
标志提供的classpath的值时,为什么要编译此文件? 通过使用带有-verbose
标志的javac
可以看到答案。
javac -verbose
的输出提供“ 源文件的搜索路径”和“ 类文件的搜索路径”。 在这种情况下,“类文件的搜索路径”很重要,因为我已经将PersonIF.java
和Person.java
源文件移到了一个完全不相关的目录中,而不是在那些指定的搜索路径中。 有趣的是,即使我没有在-cp
的值中指定此JAR(甚至目录),类文件的搜索路径(以及源文件的搜索路径)仍包含archive/PersonIF.jar
。 这表明Oracle提供的Java编译器考虑在类Class-Path
上指定的任何JAR的MANIFEST.MF
的Class-Path
头中指定的类路径内容。
下一个屏幕快照演示了如何运行新编译的Main.class
类,以及PersonIF.class
从archive/PersonIF.jar
获取依赖PersonIF.class
archive/PersonIF.jar
而无需在传递给Java应用程序启动程序的java -cp
标志的值中指定依赖PersonIF.class
。 我希望运行时行为是这种方式,尽管坦白地说我从未尝试过,甚至从未考虑过使用其MANIFEST.MF
文件没有Main-Class
标头(不可执行的JAR)的JAR来执行此操作。 在此示例中, Person.jar
清单文件未指定Main-Class
头,而仅指定了Class-Path
头,但是在使用java
调用时仍能够在运行时使用此类路径内容。
本文的最终演示涉及从JAR文件中删除Class-Path
标头和关联的值,并尝试使用javac
和相同的命令行指定的classpath进行编译。 在这种情况下,包含Person.class
的JAR被称为Person2.jar
,下面的屏幕快照演示了其MANIFEST.MF
文件没有Class-Path
标头。
下一个屏幕快照展示了使用javac
现在失败的原因,这是因为,正如预期的那样,没有在类路径上显式指定PersonIF.class
,并且不再通过引用JAR的MANIFEST.MF
Class-Path
头使它可用。类路径。
从上一个屏幕快照中我们可以看到,源文件和类文件的搜索路径不再包含archive/PersonIF.jar
。 没有可用的JAR, javac
将无法找到PersonIF.class
并报告错误消息:“找不到PersonIF.class
类文件。”
一般观察
MANIFEST.MF
文件中的Class-Path
标头不依赖于存在于同一JAR的MANIFEST.MF
文件中的Main-Class
标头。- 具有
Class-Path
清单标头的JAR将使这些类路径条目可用于Java类加载器,而不管该JAR是使用java -jar ...
执行还是仅放置在较大Java应用程序的类路径上。
- 具有
- 因为在JAR清单文件中使用
Class-Path
的范围并不限于正在执行其Main-Class
JAR,所以这些依赖可能潜在地无意中满足了类依赖(即使版本不正确),而不是解析明确指定的classpath条目。 在构造带有指定Class-Path
清单的JAR时,或在清单文件中使用带有Class-Path
的第三方JAR时,建议谨慎。 - 有时低估了JAR清单文件的重要性,但是该主题提醒人们了解特定JAR清单文件中的内容的有用性。
- 本主题提醒您可以不时运行
javac
而无需-verbose
来查看其最新信息即可收集的见解。 - 每当将JAR放置在
javac
编译器或java
应用程序启动器的类路径上时,您不仅在类路径中的那个JAR中放置了更多的类定义; 您还将在该编译器或应用程序启动器的Class-Path
上放置该JAR清单清单的Class-Path
引用的所有类和JAR。
结论
Java类加载器可以在许多地方加载用于构建和运行Java应用程序的类。 正如本文所展示的,JAR的MANIFEST.MF
文件的Class-Path
标头是另一个影响点,可以影响类加载器在运行时和编译时加载的类。 使用Class-Path
不会只影响“可执行”的JAR(在清单文件中指定了Main-Class
标头,并使用java -jar ...
运行),但可能会影响已加载的类以进行编译以及任何Java应用程序执行,其中带有包含Class-Path
标头的清单文件的JAR位于类路径上。
翻译自: https://www.javacodegeeks.com/2015/09/jar-manifest-class-path-is-not-for-java-application-launcher-only.html
java launcher
java launcher_JAR清单类路径不仅适用于Java Application Launcher相关推荐
- JAR清单类路径不仅适用于Java Application Launcher
自从我开始学习Java以来,我几乎已经知道, 清单文件中的Class-Path标头字段为可执行JAR (具有由另一个称为Main-Class清单指定应用程序起点的 JAR)指定相对运行时类路径. ...
- java 根据类名示例化类_如何使用示例从Java中的类路径加载资源
java 根据类名示例化类 Java中的类路径不仅用于加载.class文件,而且还可以用于加载资源,例如属性文件,图像,图标,缩略图或任何二进制内容. Java提供了API来将这些资源读取为Input ...
- 如何使用示例从Java中的类路径加载资源
Java中的类路径不仅用于加载.class文件,而且还可以用于加载资源,例如属性文件,图像,图标,缩略图或任何二进制内容. Java提供了API来将这些资源读取为InputStream或URL. 假设 ...
- java获取其他类的线程,使用Java实现面向对象编程——第七章 多线程
1.进程:是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间): Eg:用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间.当用户再次点击左面的IE浏览器, ...
- java 加载类java_深入研究Java类加载机制
深入研究Java类加载机制 类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行. 研究类加载机制的第二个目的是让程序能动态的控制类加载,比 ...
- java教务系统类设计_基于Java EE体系的高校教务管理系统的设计开发
<基于Java EE体系的高校教务管理系统的设计开发>由会员分享,可在线阅读,更多相关<基于Java EE体系的高校教务管理系统的设计开发(3页珍藏版)>请在人人文库网上搜索. ...
- java遍历一个类的属性名,java遍历对象属性
java对象动态添加属性,Class对象和Java反射机制,java遍历对象属性,js对象动态添加属性 java 对象动态添加属性,Class对象和Java反射机制,java遍历对象属性,js对象动态 ...
- 取 java 程序运行的路径_获取Java程序运行的路径 | 获取当前jar包的路径
经过试验,不管是否是Jar包,不管是否是Tomcat部署,以下三个方法均可实现. package test; public class MyPath { public static String ge ...
- java中utilities类_servletutilities属于哪个java包
Servlet教程 Java Servlet 和 JSP教程 1 概述 1.1 Java Servlet及其特点 Servlet是Java技术对CGI编程的回答.Servlet程序在服务器端运行,动态 ...
最新文章
- 图解Ollydbg简单逆向操作案例
- 关于ArcGIS JS API中的map高度为400px的问题解决
- PanDownload复活了!速度60MB/s!
- python dataframe取列名_python – 获取列名在DataFrame中按其值排序
- init与clinit的区别
- 特征选择 回归_如何执行回归问题的特征选择
- subList?? subString???
- 16.04编译android 7.0,ubuntu16.04 编译Android5.1报错
- 小程序css之圆角边框
- 读书笔记 - 《皇上走了》
- 前景背景分离方法(二)高斯混合模型法GMM(Gaussian Mixture Model)
- 苹果怎么删除通讯录联系人_苹果手机通讯录怎么恢复?这才是正确的打开方式!...
- 使用 IntelliJ IDEA 导入 Spark源码及编译 Spark 源代码
- [LeetCode]129. Sum Root to Leaf Numbers路径数字求和
- html显示mysql图片路径_从MYSQL数据库取出微信emoji表情在web html上显示
- SLAM学习----使用rplidar运行Hector算法
- 业务系统+电子签章开放平台,快速构建个性化的电子签署应用
- Kong 网关 | Rate Limiting 限流
- (一)注册微信个人订阅号
- Windows下的pixhawk环境搭建