Java扩展机制可加载所有JAR

Java扩展机制在Java教程中被描述为“一种标准的,可伸缩的方式,以使自定义API可供Java平台上运行的所有应用程序使用。” 如了解扩展类加载中所述 ,“扩展框架利用类加载委托机制”,其中扩展类在rt.jar (和相关的JAR)中的引导类之后,但在从典型类路径加载的类之前加载。

扩展目录的工作方式与类路径有点类似,因为扩展目录的一部分是类加载机制的一部分,扩展目录中JAR中可用的类对Java应用程序可用。 但是有一些关键的区别,下面将重点介绍其中一些。

特性 类路径 扩展机制(可选软件包)
范围 通常针对特定应用
  • -classpath / -cp
  • java.class.path
  • 可执行JAR清单的类路径

主机上可能所有的JRE

  • CLASSPATH环境变量
在特定JRE中运行的所有JVM
  • java.ext.dirs

所有主持人的JRE

  • Solaris: /usr/jdk/packages/lib/ext
  • Linux: /usr/java/packages/lib/ext
  • Windows: %SystemRoot%\Sun\Java\lib\ext
如何指定 .jar文件
  • 通过名称明确指定(包括.jar
  • 通配符(*)将所有具有.jar扩展名的所有JAR文件匹配

.class文件

  • 包含指定的.class文件的目录
加载指定目录中的所有JAR文件(即使扩展名不是.jar或根本没有扩展名)。
类加载顺序 引导程序和扩展加载之后。 在引导程序之后但在类路径之前。

最值得一提的最重要观察结果之一是,即使扩展名机制没有.jar扩展名,其扩展机制仍会提取扩展名目录中的所有JAR格式文件。 这样做的含义是,虽然可以将位于类路径目录中的JAR的名称更改为.jar以外的扩展名,以使通配符不起作用,但该技术不适用于扩展名目录。

我将在本文中使用一些简单的示例来演示其中的一些差异。 接下来的两个代码清单是一个非常简单的HelloWorld类和一个名为Main的主应用程序类,它使用HelloWorld类。

HelloWorld.java

public class HelloWorld
{@Overridepublic String toString(){return "Hello, World!";}
}

Main.java

import static java.lang.System.out;public class Main
{public static void main(final String[] arguments){out.println(new HelloWorld());}
}

为了演示类路径和扩展机制( 可选软件包 )之间的主要区别,我将把已编译的HelloWorld.class文件归档到一个名为HelloWorld.jar的JAR中,并将其放置在与已编译的Main.class文件不同的目录中。

为了演示传统类路径的用法,我将HelloWorld.jar文件放置在名为C:\hello的目录中,并将通过通配符(*)访问该JAR,以便Main使用。 接下来的两个屏幕快照对此进行了演示。

settingUpClassPathForHelloWorldExample

runningHelloWorldWithWildcardJarOnClasspath

前面的两个图像表明,即使我已将Java Main应用程序从当前目录中删除,Java Main应用程序仍然可以加载HelloWorld.class文件,因为已明确告知Java启动程序 (通过-classpath选项)在C:\hello查找它C:\hello 使用扩展机制(可选软件包),可以加载类而无需将其放在同一目录中并且没有明确的类路径规范。 这显示在下一个屏幕快照中。

runningHelloWorldWithoutClasspathUsingExtensions

上一个屏幕快照展示了Java启动器甚至不需要在同一目录中或在其类路径中指定的HelloWorld.class时,该类位于扩展(可选软件包)目录中的JAR中。 人们通常认为这是使用扩展机制的好处,因为使用该JRE的所有应用程序(或主机上可能的所有应用程序)都可以看到相同的类,而无需在类路径中明确指定它们。

使用指示应用程序从JAR加载类的传统类路径方法,包含.class文件的JAR文件需要以.jar扩展名结尾。 下一个屏幕快照演示了在同一类路径引用的目录中将HelloWorld.jar重命名为HelloWorld.backup时发生的情况。

无法运行RunHelloWorldWithoutJarExtensionInClassPathJar

最后一张图片演示了当类路径引用目录中的JAR文件没有.jar扩展名时,遇到NoClassDefFoundError 。 可能有些令人惊讶的是,扩展(可选软件包)机制的工作方式不同。 而是,将在扩展名指定目录中加载所有JAR文件,而不管其扩展名如何,即使它们具有文件扩展名也是如此。 在下一个屏幕图像中将对此进行演示。

runningHolaWorldWithoutClasspathUsingExtensionWithNoJarExtension

上一张图像演示了将扩展目录中的JAR文件重命名为没有任何文件扩展名不会阻止类加载器加载该JAR的类。 换句话说,类加载机制基于文件类型而不是文件名或扩展名来加载指定扩展目录中的所有JAR文件。 正如Optional Packages Overview总结的那样,“对于任何特定的JAR文件本身或其中包含的使其成为已安装的可选软件包的类,没有什么特别的。 由于它位于jre / lib / ext中,因此它是一个已安装的可选软件包。”

在扩展目录内的JAR中放置太多类定义会带来一些风险和弊端 。 例如,当人们看到在类路径上显式指定的类具有所涉及的方法时,为什么会发生NoSuchMethodError可能令人发狂 。 我之前已经写过 NoSuchMethodError的许多潜在原因之一,但是扩展目录中JAR文件中遗忘的过时和过时的类定义是另一个潜在原因。 接下来演示。

接下来的两个代码清单显示Main.javaHelloWorld.java修订版。 特别是, HelloWorld具有Main新版本调用的全新方法。 在这种情况下,当我运行Main时,我将把新编译的HelloWorld.class文件保留在同一目录中,以证明扩展目录中JAR中的HelloWorld.class的旧版本优先于新版本。当前目录中的热点HelloWorld.class

修改后的Hello World.java(新方法)

public class HelloWorld
{@Overridepublic String toString(){return "Hello, World!";}public String directedHello(final String name){return "Hello, " + name;}
}

修改后的Main.java

import static java.lang.System.out;public class Main
{public static void main(final String[] arguments){final HelloWorld helloWorld = new HelloWorld();out.println(helloWorld);out.println(helloWorld.directedHello("Dustin"));}
}

runningHelloWorldWithNewMethodNoSuchMethodErrorDueToExtensionsJar

上一张图片展示了extensions目录中现在过时的HelloWorld类定义优先于同一目录中的HelloWorld新类定义。 即使当我在类路径上指定当前目录时,扩展目录中的旧版本也具有优先权。 这在下一个屏幕快照中显示,该快照还显示扩展目录中“隐藏”较新JAR及其类的较新方法的JAR甚至都没有以.jar扩展名命名。

runningHelloWorldOnCPWithNewMethodNoSuchMethodErrorDueToExtensionsJar

刚刚演示的示例甚至都不是在指定的扩展目录(或多个目录)中忘记JAR可能导致的最困难的情况。 在那个例子中,至少我有一个NoSuchMethodError来提醒我一个问题。 当旧类定义具有相同的方法签名但具有过时的方法实现时,可能存在调试甚至可能更加困难的情况。 在这种情况下,可能没有任何错误,异常或可抛出,但是应用程序逻辑将无法正常工作或无法正常工作。 以前的功能可能在代码库中存在一段时间,甚至在被认为是问题之前,尤其是在缺少单元测试和其他测试的情况下。

使用extensions目录可以使开发人员更轻松,因为存在于extensions目录(或多个目录)中的JAR文件中的类可用于与extensions目录关联的JRE中的所有应用程序(如果使用操作系统,还可以与主机上的所有JRE关联)使用。基于主机的扩展目录。 但是,过于自由地使用目录存在一定的风险。 很容易忘记,该目录中JAR中的过时类定义正在阻止类加载器加载类定义的较新的,看似明显的版本。 当发生这种情况时,使开发人员的生活变得更轻松的扩展(可选软件包)机制现在变得更加困难。

Elliotte Rusty Harold提供了有关使用扩展(可选软件包)机制的警告,“虽然这看起来很方便,但这也是一个长期错误……迟早(可能不久),您将加载错误版本的类从您根本没有想过的地方开始,就浪费了很多时间进行调试。” Java教程还建议您谨慎(我强调了这一点),“由于此机制扩展了平台的核心API,因此应谨慎使用它 。 尽管它也可能适用于站点范围的接口,但最通常用于标准化接口(如Java Community Process定义的接口)。”

尽管扩展(可选软件包)机制与类路径机制相似,并且两者均用作类加载的一部分,但要注意两者之间的差异。 特别是,请务必记住,将加载位于引用为扩展目录的目录中的所有JAR文件(即使它们没有.jar文件扩展名)。 重命名这些JAR甚至更改其文件扩展名都不足以使类加载忽略它们。 另一方面,对于classpath,重命名JAR足以防止在classpath显式指定单个JAR文件时进行加载,并且即使classpath使用通配符(*)来指定所有JAR,更改文件扩展名通常也足以防止加载目录。

在某些情况下,扩展(可选软件包)机制是适当的选择,但这些情况似乎很少见。 在处理无法解释的NoSuchMethodError时,请记住扩展机制(可选软件包),这一点也很重要,以便人们可以检查出该违规者是否住在该目录中。

翻译自: https://www.javacodegeeks.com/2014/10/java-extension-mechanism-loads-all-jars.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361706.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++的文艺复兴: Why C++? 王者归来

因为又有人叫我去Quora的C2C站去回答问题了,这回是 关于 《2012 不宜进入的三个技术点ActionScript,Thread 和 C, C争议的争议最大。(要我说,.NET比C更需要慎重进入,呵)。我就在这里回复一下这个问题吧。 正好我前段时…

Drools和jBPM KIE A​​pps平台

随着Drools和jBPM(KIE)6系列出现了一个新的工作台,并有望最终实现用户的可扩展性。 我终于有了一些预告片,以显示此工作原理以及所存储的内容。 确保选择1080p并全屏显示,以达到最佳效果。 (点击放大&…

js 严格模式

一、概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。 设立"严格模式"的目的,主要有以下…

模态对话框和全选反选

一、目标 制作一个表格,第一行分别为选择、主机名和端口增加一个按钮,名称为添加点击添加按钮,出现一个半透明的遮罩层,遮罩层中间有个弹出框弹出框中有两个输入框,分别为主机名和端口,还有两个按钮&#…

(转)iReaper for wp7正式发布

原文地址:http://www.cnblogs.com/AlexCheng/archive/2012/02/06/2339968.htmliReaper for windows phone 7今天正式发布了。有windows phone 7手机的朋友可以通过手机在线收听收看webcast中文课程。只要你有网络任何时间任何地点都可以学习微软技术,为您…

Neo4j:Cypher –避免热切

当心渴望的管道 尽管我喜欢Cypher的LOAD CSV命令使它容易地将数据获取到Neo4j中的方法,但它目前打破了最不惊奇的规则,因为它急切地在所有行中加载某些查询,即使是那些使用定期提交的查询。 这是我的同事Michael在第二篇博客文章中指出的&a…

一步步构建大型网站架构 [转]

来源: itivy 原文链接 之前我简单向大家介绍了各个知名大型网站的架构,MySpace的五个里程碑、Flickr的架构、YouTube的架构、PlentyOfFish的架构、WikiPedia的架构。这几个都很典型,我们可以从中获取很多有关网站架构方面的知识,看了之后你…

img、列表和table标签

一、img图片 <body><a href"https://www.fmtxt.com"><img src"images/1.jpg" title"哆啦A梦" style"height: 200px; width: 200px " alt"哆啦A梦"/></a></body>1. 放在 a 标签中&#xff0c…

Java基础笔记之数据类型

一、数据类型 &#xff08;一&#xff09;8种基本数据类型(内置数据类型\C#中为值类型) 字符长度&#xff1a;1byte 8 bit;布尔&#xff1a;可认为是 1byte (8 bit);字符&#xff1a;char&#xff1a;2/16整型:short: 2/16int: 4/32long: 16/64浮点型:float: 8/32double: 16/6…

SSTI模板注入基础(Flask+Jinja2)

文章目录 一、前置知识1.1 模板引擎1.2 渲染 二、SSTI模板注入2.1 原理2.2 沙箱逃逸沙箱逃逸payload讲解其他重要payload 2.3 过滤绕过点.被过滤下划线_被过滤单双引号 "被过滤中括号[]被过滤关键字被过滤 三、PasecaCTF-2019-Web-Flask SSTI参考文献 一、前置知识 1.1 模…

关于Java的十件事

那么&#xff0c;您从一开始就一直在使用Java&#xff1f; 还记得曾经被称为“ Oak”的日子&#xff0c;OO仍然是热门话题&#xff0c;C 人士认为Java没有机会&#xff0c;Applet还是一件事吗&#xff1f; 我敢打赌&#xff0c;您至少不了解以下一半内容。 让我们从本周开始&a…

注释,无处不在的注释

十年前的2004年 &#xff0c; Java 1.5开始提供注释。 很难想象没有此功能的代码。 实际上&#xff0c;首先引入了注释&#xff0c;以减轻开发人员编写繁琐的样板代码的痛苦&#xff0c;并使代码更具可读性。 考虑一下J2EE 1.4&#xff08;没有可用的注释&#xff09;和Java EE…

JZTK项目 驾照题库项目servlet层得到的json字符串在浏览器中 汉字部分出现问号?无法正常显示的解决方法

servlet层中的代码如下&#xff1a; package com.swift.jztk.servlet;import java.io.IOException;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletReque…

【RTOS】基于V7开发板的uCOS-III,uCOS-II,RTX4,RTX5,FreeRTOS原版和带CMSIS-RTOS V2封装层版全部集齐...

RTOS模板制作好后&#xff0c;后面堆各种中间件就方便了。 1、基于V7开发板的最新版uCOS-II V2.92.16程序模板&#xff0c;含MDK和IAR&#xff0c;支持uC/Probehttps://www.cnblogs.com/armfly/p/11255981.html 2、基于V7开发板的最新版uCOS-III V3.07.03程序模板&#xff0c;含…

三极管开关电路设计(转)

三极管开关电路设计 三极管除了可以当做交流信号放大器之外&#xff0c;也可以做为开关之用。严格说起来&#xff0c;三极管与一般的机械接点式开关在动作上并不完全相同&#xff0c;但是它却具有一些机械式开关所没有的特点。图1所示&#xff0c;即为三极管电子开关的基本电路…

OpenShift上具有NetBeans的Java EE

今天是慕尼黑的NetBeans日 。 我很高兴提出一个关于将Red Hat产品与我著名的IDE集成的会议。 因此&#xff0c;我一直在谈论WildFly &#xff0c; EAP &#xff0c;Git和OpenShift Online&#xff0c;并展示了使用该工具集优化开发工作流程的所有不同方式。 大约有100位与会者…

tomcat.apache startup.bat闪退两种解决方法

tomcat bin文件夹中的startup.bat闪退原因及解决方法两种 方法一&#xff1a;在启动tomcat时闪退&#xff0c;重新检查java的jre运行环境。如果环境变量忘记配置一定会导致了tomcat的闪退。 追加 Apache的bin的环境变量也放到path中 注意检查一下看 JAVA_HOME是否写错&#xff…

产生的DLL (VS2005, MATLAB7.5, mwArray)

from: http://www.simwe.com/forum/thread-801187-1-1.html 程序中使用MATLAB编译产生的DLL &#xff08;VS2005, MATLAB7.5, mwArray&#xff09; 最近有几个帖子都在讨论有关在C程序中使用MATLAB编译产生的动态链接库DLL。本 来想用原来帖子中给出的m代码作为例子&#xff0c…

启动LINUX下的TFTP服务器

第一步: 我们要确认,LINUX下是不是安装了TFTP-SERVER. 在LINUX下输入: rpm -q tftp-server 如出现如下回复: tftp-server-0.39-2 则表示tftp-server已安装. 第二步: 修改TFTP启动脚本: 方法一: 需要修改ftptpd的启动脚本vi /etc/xinetd.d/tftp加上 disable no 此时即可启动tf…

简单代码生成器原理剖析(一)

上篇文章&#xff08;深入浅出三层架构&#xff09;分析了简单三层架构的实现。包括Model,DAL&#xff08;数据访问层&#xff09;,BLL&#xff08;业务逻辑层&#xff09;的实现。 实际开发中&#xff0c;由于重复代码的操作&#xff0c;会花费大量时间&#xff0c;如果以代码…