331

在 Java 中,您经常会看到一个 META-INF 文件夹,其中包含一些元文件。这个文件夹的用途是什么,我可以放什么?

4

13 回答 13

175

来自官方 JAR 文件规范(链接到 Java 7 版本,但至少从 v1.3 开始文本没有改变):

META-INF 目录

META-INF 目录中的以下文件/目录被 Java 2 平台识别和解释,以配置应用程序、扩展、类加载器和服务:

  • MANIFEST.MF

用于定义扩展和包相关数据的清单文件。

  • INDEX.LIST

此文件由-ijar 工具的新“”选项生成,其中包含在应用程序或扩展中定义的包的位置信息。它是 JarIndex 实现的一部分,并被类加载器用来加速其类加载过程。

  • x.SF

JAR 文件的签名文件。“x”代表基本文件名。

  • x.DSA

与具有相同基本文件名的签名文件关联的签名块文件。该文件存储了对应签名文件的数字签名。

  • services/

该目录存储所有服务提供者配置文件。

自 Java 9 以来实现JEP 238的新功能是多版本 JAR。将看到一个子文件夹versions。这是一项允许将用于不同 Java 版本的类打包到一个 jar 中的功能。

于 2008-09-16T07:57:14.757 回答
72

一般来说,您不应该自己在 META-INF 中添加任何内容。相反,您应该依赖于您用来打包 JAR 的任何东西。这是我认为 Ant 真正擅长的领域之一:指定 JAR 文件清单属性。说这样的话很容易:

<jar ...>
    <manifest>
        <attribute name="Main-Class" value="MyApplication"/>
    </manifest>
</jar>

至少,我认为这很容易...... :-)

关键是 META-INF 应该被认为是一个内部 Java目录。不要惹它!您想要包含在 JAR 中的任何文件都应该放在其他一些子目录或 JAR 本身的根目录中。

于 2008-09-16T08:05:30.120 回答
28

我注意到一些 Java 库已经开始使用 META-INF 作为目录,其中包含应该与 JAR 一起打包并包含在 CLASSPATH 中的配置文件。例如,Spring 允许您使用以下方法导入类路径上的 XML 文件:

<import resource="classpath:/META-INF/cxf/cxf.xml" />
<import resource="classpath:/META-INF/cxf/cxf-extensions-*.xml" />

在这个例子中,我直接引用了Apache CXF 用户指南。在我从事的一个项目中,我们必须允许通过 Spring 进行多级配置,我们遵循这个约定并将我们的配置文件放在 META-INF 中。

当我反思这个决定时,我不知道将配置文件简单地包含在特定的 Java 包中而不是 META-INF 中究竟有什么问题。但它似乎是一个新兴的事实上的标准。无论是那个,还是一个新兴的反模式:-)

于 2008-11-24T21:38:40.633 回答
15

META-INF 文件夹是MANIFEST.MF文件的主目录。此文件包含有关 JAR 内容的元数据。例如,有一个名为 Main-Class 的条目,它使用可执行 JAR 文件的静态 main() 指定 Java 类的名称。

于 2008-09-16T08:00:55.933 回答
13

Maven 中的 META-INF

在 Maven 中,可以理解META-INF文件夹是因为Standard Directory Layout,它按照名称约定将您的项目资源打包到 JAR 中:放置在${basedir}/src/main/resources目录中的任何目录或文件都打包到您的 JAR 中从 JAR 的底部开始具有完全相同的结构。

文件夹${basedir}/src/main/resources/META-INF通常包含.properties文件,而 jar 中包含生成的MANIFEST.MFpom.propertiespom.xml等文件。像Spring这样的框架也用于classpath:/META-INF/resources/提供 Web 资源。

有关更多信息,请参阅如何将资源添加到我的 Maven 项目

于 2015-01-12T15:48:14.720 回答
12

您也可以在其中放置静态资源。

例如:

META-INF/resources/button.jpg 

并通过 web3.0-container 获取它们

http://localhost/myapp/button.jpg

> 阅读更多

/META-INF/MANIFEST.MF 具有特殊含义:

  1. 如果您使用 jar 运行,java -jar myjar.jar org.myserver.MyMainClass您可以将主类定义移动到 jar 中,这样您就可以将调用缩小到java -jar myjar.jar.
  2. 如果您使用java.lang.Package.getPackage("org.myserver").getImplementationTitle().
  3. 您可以参考您喜欢在 Applet/Webstart 模式下使用的数字证书。
于 2013-01-15T14:50:03.123 回答
7

在此处添加信息,META-INF 是一个特殊文件夹,其ClassLoader处理方式与 jar 中的其他文件夹不同。嵌套在 META-INF 文件夹中的元素不会与它之外的元素混合。

把它想象成另一个根。从Enumerator<URL> ClassLoader#getSystemResources(String path)方法等角度来看:

当给定路径以“META-INF”开头时,该方法搜索嵌套在类路径中所有 jar 的 META-INF 文件夹内的资源。

当给定路径不以“META-INF”开头时,该方法在类路径中所有 jar 和目录的所有其他文件夹(META-INF 之外)中搜索资源。

如果您知道该getSystemResources方法特别对待的另一个文件夹名称,请评论它。

于 2016-04-22T18:21:31.420 回答
5

只是补充一下这里的信息,如果是 WAR 文件,META-INF/MANIFEST.MF 文件为开发人员提供了一个工具来启动容器的部署时间检查,以确保容器可以找到您的应用程序的所有类取决于。这确保了万一您错过了一个 JAR,您不必等到您的应用程序在运行时崩溃才意识到它丢失了。

于 2009-10-21T15:21:18.890 回答
5

我最近一直在思考这个问题。似乎对 META-INF 的使用没有任何限制。当然,关于将清单放在那里的必要性有一定的限制,但似乎没有任何禁止将其他东西放在那里。

为什么会这样?

cxf 案可能是合法的。这是另一个建议使用此非标准来解决 JBoss-ws 中的一个讨厌的错误的地方,该错误会阻止服务器端对 wsdl 的模式进行验证。

http://community.jboss.org/message/570377#570377

但似乎真的没有任何标准,任何你不应该。通常这些东西是非常严格的定义,但由于某种原因,这里似乎没有标准。奇怪的。似乎 META-INF 已成为任何无法以其他方式轻松处理的所需配置的包罗万象的地方。

于 2011-10-11T03:45:10.437 回答
3

如果您使用的是 JPA1,则可能必须persistence.xml在其中放置一个文件,该文件指定您可能要使用的持久性单元的名称。持久性单元提供了一种方便的方法来指定一组元数据文件、类和包含要在一个分组中持久化的所有类的 jar。

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

// ...

EntityManagerFactory emf =
      Persistence.createEntityManagerFactory(persistenceUnitName);

在此处查看更多信息: http ://www.datanucleus.org/products/datanucleus/jpa/emf.html

于 2009-10-22T20:42:29.727 回答
2

所有答案都是正确的。Meta-inf 有很多用途。另外,这里是一个关于使用tomcat容器的例子。

转到 Tomcat Doc并检查“标准实现 > copyXML ”属性。

说明如下。

如果您希望在部署应用程序时将嵌入在应用程序中的上下文 XML 描述符(位于 /META-INF/context.xml)复制到拥有主机的 xmlBase,则设置为 true。在随后的启动中,复制的上下文 XML 描述符将优先于嵌入在应用程序中的任何上下文 XML 描述符使用,即使嵌入在应用程序中的描述符是更新的。该标志的值默认为 false。注意如果拥有 Host 的 deployXML 属性为 false 或拥有 Host 的 copyXML 属性为 true,则该属性将不起作用。

于 2015-01-13T15:04:35.507 回答
0

您的 META-INF 文件夹中有 MANIFEST.MF 文件。您可以定义必须有权访问的可选或外部依赖项。

例子:

考虑您已经部署了您的应用程序并且您的容器(在运行时)发现您的应用程序需要一个不在 lib 文件夹内的库的较新版本,在这种情况下,如果您在其中定义了可选的较新版本,MANIFEST.MF那么您的应用程序将引用从那里依赖(并且不会崩溃)。

Source:Head First Jsp & Servlet

于 2015-11-10T21:45:58.057 回答
0

此外,META-INF 文件夹现在也用于多版本 jars。这是一个允许将用于不同 Java 版本的类打包在一个 jar 中的功能,例如,在一个 jar 中包含一个用于 Java 11 的类,该类具有 Java 11 提供的新功能,也适用于 Java 8,其中 Java 8 的不同类包含的功能较少。例如,如果较新的 Java 版本提供了增强的、不同的或新的 API 方法,这些方法由于 API 违规而在早期版本中不起作用。然后会看到一个子文件夹versions

于 2021-12-18T23:38:17.093 回答