跨多个公共库共享单个类加载器是否安全 元素?

问题描述 投票:1回答:1

以下是Tomcat中我的server.xml文件的片段:

<Host name="client9001.example.com" appBase="/web/my-product-code" autoDeploy="true"></Host>
<Host name="client9002.example.com" appBase="/web/my-product-code" autoDeploy="true"></Host>
<Host name="client9003.example.com" appBase="/web/my-product-code" autoDeploy="true"></Host>
...
<Host name="client9254.example.com" appBase="/web/my-product-code" autoDeploy="true"></Host>

众所周知,每个Host元素都会创建自己的WebappClassloader实例,这使得每个主机都完全隔离且安全。通过此设置,我可以安全地使用一个Tomcat实例为X客户提供服务,每个客户都在不同的子域下提供服务。此设置可防止客户B的操作操纵客户A的对象。

但是,这会产生对非堆空间的不可扩展需求(因为每个类都加载X次),我想知道是否可以为所有主机创建共享类加载器。我知道Tomcat支持这种事情(使用https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html#Class_Loader_Definitions中的“Common”类加载器)但我的问题是这样做是否安全。我的意思是,我可以通过消除所有静态字段来使我自己的类安全,但这足够了吗?我很担心第三方库,比如Spring Framework,Log4J,Joda-time以及我的产品代码附带的其他几个库。

我已经使用反射来识别这些类中的所有静态变量,我已经发现了252个静态和非最终字段以及5772个静态和最终字段,这些都在第三方代码中(我自己的代码只有我将消除的3个领域)。

我应该走这条路并审查所有这6027个领域吗?我的意思是,这整个想法是个坏主意吗?如果是这样,那么在“Common”类加载器中可以共享什么样的代码?

有没有强有力的证据证明所有这些着名的框架都可以安全地分享,或者我应该把所有东西都视为不安全 - 直到证明 - 否则?

java spring tomcat log4j c3p0
1个回答
0
投票

我会非常谨慎......并决定性能是否值得冒风险

我在考虑假设的情况,你可能会遇到使用共享ClassLoader的一些意想不到的后果......

我看了一下Log4J,它通过LogManager创建了记录器,它扩展了java.util.logging.LogManager,用于维护一组关于Loggers和日志服务的共享状态。

想象一下这些客户端执行private static final Logger LOGGER = LogManager.getLogger();为每个主机创建记录器的情况

 <Host name="client9001.example.com">  
 <Host name="client9002.example.com">
 <Host name="client9003.example.com"> 

 <Host name="BADclient.example.com"> 

因为LogManager是在所有主机之间静态共享的,所以坏客户端可以调用LogManagers.getLoggerNames();,它会将所有已注册记录器的列表返回给该静态LogManager实例,并且会泄漏有关在同一个tomcat实例上运行的其他客户端的信息/能够删除eventlisteners对于使用同一类的其他主机(**我还没试过这个**)

基本上,您希望将在JVM上运行的所有主机(以及所有将来的主机)之间100%共享的代码放在一起。常见的例子是初始化JDBC连接。

另外在代码维护方面,如果您打算走下兔洞,并尝试查看所有静态方法/字段..每次更新第三方导入时,您都必须再次查看它们,确保没有引入任何内容...甚至可能会检查第三方进口的进口情况

可能会发现这个问题引人注目Tomcat classloader violates delegating policy,因为他询问在Tomcat中使用常见类加载器的危险

© www.soinside.com 2019 - 2024. All rights reserved.