Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不允许在java扩展中调用某些类_Java_Jar_Extensibility - Fatal编程技术网

不允许在java扩展中调用某些类

不允许在java扩展中调用某些类,java,jar,extensibility,Java,Jar,Extensibility,我们正在构建一个引擎,它允许我们在任何时候添加新的jar文件,加载这些jar文件并查找某些特定功能,并运行公开该功能的代码。目前的计划是使用ServiceLoader来实现这一点(只是一个额外的细节;我不同意这个想法)。现在让我们假设我们完全控制要加载哪些jar文件(大假设——我想我最终也会发布一些关于这方面的信息) 考虑到所有这些,我想将这些扩展中的访问限制到某些类。举个假例子,我们希望确保他们使用的不是java.io.PrintStream,而是our.better.PrintStreamS

我们正在构建一个引擎,它允许我们在任何时候添加新的jar文件,加载这些jar文件并查找某些特定功能,并运行公开该功能的代码。目前的计划是使用ServiceLoader来实现这一点(只是一个额外的细节;我不同意这个想法)。现在让我们假设我们完全控制要加载哪些jar文件(大假设——我想我最终也会发布一些关于这方面的信息)

考虑到所有这些,我想将这些扩展中的访问限制到某些类。举个假例子,我们希望确保他们使用的不是
java.io.PrintStream
,而是
our.better.PrintStreamSolution


我真的不知道我能在这里做什么。因为目前,我们拥有将作为扩展发布的代码,所以我们可以进行非常彻底的代码检查,但我宁愿在安装时进行静态分析,或者在运行时实际抛出错误。你知道如何做到这一点吗?

你需要将这些API列入白名单。反射式API随处可见,因此您不能将其列入黑名单。要做到这一点,您需要使用诸如ASM之类的库来检查JAR。虽然可以将
URLClassLoader
与自定义URL连接处理程序一起使用,但我建议使用自定义类装入器。我强烈建议避免任何与全局状态相关的操作,例如创建一个特殊的类加载器来读取JAR,并重写方法“loadClass”,这样如果类加载器试图从“java.io”包加载类,它就会抛出SecurityException。大概是这样的:

protected Class loadClass(String name, boolean resolve)
                                            throws ClassNotFoundException { 
       if (name.startsWith("java.io")) 
             throw new SecurityException("java.io access not allowed on extensions");

        return super.loadClass(name,resolve); 
} 
记住在类加载器的重写findClass方法中实现类加载逻辑

如果扩展可以获得另一个类加载器(如系统类加载器)来加载“禁止”类,则此检查可能会失败


如注释所示,只有当安全管理器能够识别正在从扩展中访问包时,才有可能使用SecurityManager

如果我弄错了,请纠正我,但是扩展不能直接调用
Object.class.getClassLoader().loadClass()
来绕过您的建议吗?我有理由相信唯一的解决方案是搞乱SecurityManager,但我也没有这方面的经验,而且我不知道有谁这样做。Object.class.getClassLoader()应该返回null(实际上,JRE中的所有类都应该返回null,因为它们是由引导类加载器加载的),所以您应该非常安全。当然,他们可以使用来自引擎的类(将由系统类加载器实际加载)使用相同的技巧。是的,你是对的,支票可以绕过。我不完全理解你的答案,我想那是因为我对这个问题了解不够。有什么关于背景阅读的建议吗?这行不通。除此之外,反射式API将解决这一问题。除非直接调用方(是的,令人沮丧的API)是从祖先类加载器加载的。@TomHawtin tackline您是说类加载器解决方案不起作用还是说SecurtyManager解决方案不起作用?基于这些评论和我今天所做的研究,我的理解是类加载器解决方案不起作用。ServiceLoader有什么问题,从jar获得实现特定接口(或者我想有一个众所周知的名称)的类的更好/不同的方法是什么?@SirPentor它使用环境[全局]状态记下你们班的名字;在类加载器中查找它(具体是哪一个);使用子类的
;找到
构造函数
(不要错过此步骤);调用
newInstance
。(有可能的变化,例如使用常量字段而不是构造函数。)