Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在Java 9+中安全地访问类路径中所有资源文件的URL?

如何在Java 9+中安全地访问类路径中所有资源文件的URL?
EN

Stack Overflow用户
提问于 2018-03-29 05:31:35
回答 2查看 3.7K关注 0票数 47

我们从Java 9的发行说明中了解到

应用程序类加载器不再是java.net.URLClassLoader的实例(以前版本中从未指定的实现细节)。假设ClassLoader::getSytemClassLoader返回一个URLClassLoader对象的代码需要更新。

这破坏了旧代码,该代码扫描类路径如下:

Java <= 8

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
URL[] ressources = ((URLClassLoader) classLoader).getURLs();

它会遇到一个

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java.lang.ClassCastException: 
java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to 
java.base/java.net.URLClassLoader

因此,对于Java 9+,提出了以下解决方案,作为Apache Ignite项目的PR,根据JVM运行时选项中的调整来工作:--add-opens java.base/jdk.internal.loader=ALL-UNNAMED。然而,正如在下面的评论中所提到的,这个PR从未合并到他们的主分支中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 * Java 9 + Bridge to obtain URLs from classpath...
 */
private static URL[] getURLs(ClassLoader classLoader) {
    URL[] urls = new URL[0];

    try {
        //see https://github.com/apache/ignite/pull/2970
        Class builtinClazzLoader = Class.forName("jdk.internal.loader.BuiltinClassLoader");

        if (builtinClazzLoader != null) {
            Field ucpField = builtinClazzLoader.getDeclaredField("ucp");
            ucpField.setAccessible(true);

            Object ucpObject = ucpField.get(classLoader);
            Class clazz = Class.forName("jdk.internal.loader.URLClassPath");

            if (clazz != null && ucpObject != null) {
                Method getURLs = clazz.getMethod("getURLs");

                if (getURLs != null) {
                    urls = (URL[]) getURLs.invoke(ucpObject);
                }
            }
        }

    } catch (NoSuchMethodException | InvocationTargetException | NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
        logger.error("Could not obtain classpath URLs in Java 9+ - Exception was:");
        logger.error(e.getLocalizedMessage(), e);
    }
    return urls;
}

然而,由于在这里使用反射,这会引起一些严重的头痛。这是一种反模式,受到禁用-apis maven插件的严格批评。

禁止方法调用:使用java.lang.reflect.AccessibleObject#setAccessible(boolean)反射处理访问标志的方法在SecurityManagers中失败,很可能不再适用于Java9中的运行时类。

问题

是否有一种安全的方法来访问类/模块路径中的所有资源URLs的列表,可以由给定的类加载器在OpenJDK 9/10中访问,而无需使用sun.misc.*导入(例如通过使用Unsafe)?

更新(与评论相关)

我知道,我能做到

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 String[] pathElements = System.getProperty("java.class.path").split(System.getProperty("path.separator"));

要获取类路径中的元素,然后将它们解析为URL,但是--据我所知--此属性只返回应用程序启动时给定的类路径。但是,在容器环境中,这将是应用服务器中的一个,可能不够,例如使用EAR包。

更新2

谢谢你的评论。我将测试,System.getProperty("java.class.path")是否可以用于我们的目的,并更新问题,这是否满足了我们的需求。

然而,似乎其他项目(可能是出于其他原因,例如Apache TomEE 8)遭受了与URLClassLoader相关的同样痛苦--因此,我认为这是一个有价值的问题。

更新3

最后,我们切换到类图,并将代码迁移到这个库中,以解决我们的用例,从而从类路径中加载绑定为JAR的ML资源。

EN

回答 2

Stack Overflow用户

发布于 2018-04-09 02:51:01

我想这是XY问题。在Java中,访问类路径上所有资源的URL不是一个受支持的操作,也不是一件好事。正如您在这个问题中已经看到的,如果您尝试这样做的话,您将一直在与框架作斗争。将有一百万种边缘情况会破坏您的解决方案(自定义类加载器、EE容器等)。

请你详述一下你为什么要这么做?

如果您有某种插件系统,并且正在寻找与代码接口的模块,这些模块可能是在运行时提供的,那么您应该使用ServiceLoader API,即:

通过在资源目录META-INF/services中放置提供者配置文件来标识打包为类路径的JAR文件的服务提供者。提供程序配置文件的名称是服务的完全限定的二进制名称。provider-configuration文件包含服务提供程序的完全限定二进制名称的列表,每一行一个。例如,假设服务提供者com.example.impl.StandardCodecs被打包到一个JAR文件中,用于类路径。JAR文件将包含一个提供者配置文件,名为: META-INF/services/com.example.CodecFactory 包含以下内容的行: com.example.impl.StandardCodecs #标准编解码器

票数 18
EN

Stack Overflow用户

发布于 2018-03-29 05:52:01

AFAIK您可以解析java.class.path系统属性以获得urls:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String classpath = System.getProperty("java.class.path");
String[] entries = classpath.split(File.pathSeparator);
URL[] result = new URL[entries.length];
for(int i = 0; i < entries.length; i++) {
    result[i] = Paths.get(entries[i]).toAbsolutePath().toUri().toURL();
}

System.out.println(Arrays.toString(result)); // e.g. [file:/J:/WS/Oxygen-Stable/jdk10/bin/]
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49557431

复制
相关文章
IBM WebSphere MQ 系列(三)配置和使用WebSphere MQ
配置和使用WebSphere MQ A.设置环境变量   在shell中执行MQ的控制命令:     ctrmqm     strmqm   若识别这些命令,则说明PATH环境变量已配置好了;   若提示找不到命令,则说明需配置Linux环境变量,指定MQ的bin路径到PATH:      可选择修改系统的环境变量(/etc/profile文件,对全部用户可见),      或只修改用户mqadmin的环境变量(/var/mqm/.bash_profile,只对当前用户可见。     下面列出前者的修改方式
Java学习123
2018/05/16
6.4K0
WebSphere MQ基础命令
基础概念 对于MQ,我们需要知道4个名词:队列管理器、队列、消息、通道;对于编程设计人员,通常更关心消息和队列,对于维护管理人员,通常 会更关心队列管理器和通道。如果我们把队列管理器比作是数据库,那么队列就是其中的一张表,消息就是表中的一条记录。 队列:我们可以简单地把队列看成一个容器,用于存放消息。 队列管理器:队列管理器构建了独立的 MQ 的运行环境,它是消息队列的管理者,用来维护和管理消息队列。 消息:MQ中的最小对象;默认情况下,消息缺省可以达到 4MB。消息可以分成持久消息和非持久消息。所谓“持久
Java学习123
2018/05/16
2.7K0
IBM WebSphere MQ 系列(二)安装MQ
一、安装WebSphere MQ之前Linux系统的配置 1.创建MQ安装目录   shell命令:  mkdir /opt/mqm   //创建安装目录  mkdir /var/mqm   //创建工作目录   2.创建MQ用户和用户组   MQ通过Linux本地的用户和用户组来管理MQ服务器,mqm用户组的下属用户成员均为MQ管理员,具有MQ服务器的全部权限。   用户组的名称必须是:mqm   用户名称可自定义,假设为:mqadmin   以root登录Linux   shell命令:     gr
Java学习123
2018/05/16
4.6K0
IBM WebSphere MQ检索邮件
如果在使用IBM WebSphere MQ的InterSystems IRIS接口时遇到问题,应该首先确定客户端是否安装正确并且可以与服务器通信。要执行这样的测试,可以使用IBM WebSphere MQ提供的示例程序。可执行文件位于IBM WebSphere MQ客户端的bin目录中。
用户7741497
2022/07/04
1.8K0
IBM WebSphere MQ 系列(四) 使用MQ命令
结合上节使用到的MQ命令,本节系统阐述MQ的命令。 一、MQ命令集合     MQ命令集合有三种命令:控制命令、MQSC(MQ脚本命令)和PCF(Programmable Command Formats,可编程的命令格式)。 二、控制命令     控制命令:用于管理 WebSphere MQ的系统配置,包括队列管理器、侦听器、通道、日志的管理。     例如:创建队列管理器(crtmqm),启动队列管理器(strmqm),启动用于运行队列管理器MQSC命令的控制台(runmqsc)、运行通道(runmqch
Java学习123
2018/05/16
4.4K0
IBM WebSphere MQ 7.5基本用法
一、下载7.5 Trial版本 http://www.ibm.com/developerworks/downloads/ws/wmq/ 这是下载网址,下载前先必须注册IBM ID,下载完成后一路Next即可(注:windows上安装时,会询问是否域环境,初次学习时,为简单起见,建议选择No) 安装完成后,MQ的Bin目录会自动添加到环境变量Path中,以后就可以直接用Dos命令行窗口操作(当然,也可以用图形化GUI方式通过IBM WebSphere MQ Explorer来管理) 注:安装时,强烈建议用管理
菩提树下的杨过
2018/01/24
3.6K0
IBM WebSphere MQ 7.5基本用法
配置IBM WEBSPHERE MQ触发器
配置IBM WEBSPHERE MQ触发器 2007-11-15 创建 一般设置MQ触发器的目的有两种, 一是自动启动发送端通道, 二是监视队列消息, 一旦发现新的消息, 则利用触发器启动相应的处理进程 如果是利用触发器自动启动发送端通道, 使用方法1, 如果是利用触发器启动用户进程, 使用方法2 方法1 A 在传输通道上设置触发器, 打开触发器控制, 类型为"第一个" B 初始队列为SYSTEM.CHANNEL.INITQ, 该队列为MQ专用的通道启动队列, 不需要手工启动其触发监视器 C 触发器数据为发
Java学习123
2018/05/16
1.9K0
发送和接收IBM WebSphere MQ消息
InterSystems IRIS为IBM WebSphere MQ提供了一个接口,可以使用该接口在InterSystems IRIS和IBM WebSphere MQ的消息队列之间交换消息。要使用此接口,必须能够访问IBM WebSphere MQ服务器,并且IBM WebSphere MQ客户端必须与InterSystems IRIS在同一台计算机上运行。
用户7741497
2022/07/04
2.9K0
延迟队列MQ
延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列。
一个风轻云淡
2022/11/13
1.1K0
延迟队列MQ
IBM WebSphere MQ 系列(一)基础知识
一、中间件    中间件处于应用软件和系统软件之间,是一种以自己的复杂换取企业应用简单化的可复用的基础软件。    在中间件产生以前,应用软件直接使用操作系统、网络协议和数据库等开发,开发者不得不面临许多很棘手的问题,如操作系统的多样性,繁杂的网络程序设计和管理,复杂多变的网络环境,数据分散处理带来的不一致性,性能和效率、安全问题等等。这些问题与用户的业务没有直接关系,但又必须解决,耗费了大量有限的时间和精力。于是,有人提出将应用软件所要面临的共性问题进行提炼、抽象,在操作系统之上再形成一个可复用的部分,供
Java学习123
2018/05/16
5.1K0
mq消息队列的作用
我们在工作中,经常用到各自各样的mq消息队列中间件,今天我们来学习一下为什么需要用消息队列,用了对我们的好处是什么?
灬沙师弟
2023/03/07
1.2K0
mq消息队列的作用
消息队列MQ
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
chenchenchen
2019/10/22
1.8K0
消息队列MQ
mq监听死信队列后如何处理
昨天试了半天为啥监听不到死信队列的消息,原因是打开方式不对,还有死信队列就一条消息,没意思。
疯狂的KK
2020/09/14
1.5K0
消息队列简介(MQ)
消息队列是一种异步的服务间通信方式,适用于无服务器和微服务架构。消息在被处理和删除之前一直存储在队列上。每条消息仅可被一位用户处理一次。消息队列可被用于分离重量级处理、缓冲或批处理工作以及缓解高峰期工作负载。
终身幼稚园
2019/07/19
2.2K0
消息队列简介(MQ)
消费端如何保证消息队列MQ的有序消费
消息队列,既然是队列就能保证消息在进入队列,以及出队列的时候保证消息的有序性,显然这是在消息的生产端(Producer),但是往往在生产环境中有多个消息的消费端(Consumer),尽管消费端在拉取消息时是有序的,但各个消息由于网络等方面原因无法保证在各个消费端中处理时有序。
Java_老男孩
2019/12/02
8620
消费端如何保证消息队列MQ的有序消费
消息队列,既然是队列就能保证消息在进入队列,以及出队列的时候保证消息的有序性,显然这是在消息的生产端(Producer),但是往往在生产环境中有多个消息的消费端(Consumer),尽管消费端在拉取消息时是有序的,但各个消息由于网络等方面原因无法保证在各个消费端中处理时有序。
用户1148394
2019/07/31
1.6K0
消费端如何保证消息队列MQ的有序消费
IBM MQ运维使用手册
操作系统版本:SUSE Linux Enterprise Server 10 SP4    32bit
loong576
2019/09/10
8K0
IBM MQ运维使用手册
线程池数量以及队列长度如何分配?
首先我们几乎可以忽略队列本身占内存的情况,主要考虑多线程取队列数据竞争问题以及线程数量
名字是乱打的
2021/12/24
1K0
IBM MQ运维使用手册
操作系统版本:SUSE Linux Enterprise Server 10 SP4    32bit
星哥玩云
2022/07/20
3.3K0
IBM MQ运维使用手册
【消息队列 MQ 专栏】消息队列之 Kafka
Kafka 最早是由 LinkedIn 公司开发一种分布式的基于发布/订阅的消息系统,之后成为 Apache 的顶级项目。主要特点如下:
芋道源码
2018/07/31
4K0
【消息队列 MQ 专栏】消息队列之 Kafka

相似问题

如何获取-抑制WebSphere MQ队列?

25

如何从WebSphere MQ监控现有队列?

28

WebSphere MQ队列创建

11

将Websphere 5.1 MDB连接到JBoss MQ队列

12

使用Ruby连接到Websphere MQ队列进行测试

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文