静态字段,classloader,web容器

http://hi.baidu.com/liangzhongbo1/blog/item/f2c3201ae4b7250c34fa41f6.html

类加载器与 Web 容器

对于运行在 Java EE™ 容器中的 Web 应用来说,类加载器的实现方式与一般的Java 应用有所不同[默认的是从父到子]。不同的 Web 容器的实现方式也会有所不同。以 Apache Tomcat 来说,每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。这是 Java Servlet 规范中的推荐做法,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全。

绝大多数情况下,Web 应用的开发人员不需要考虑与类加载器相关的细节。下面给出几条简单的原则:

每个 Web 应用自己的 Java 类文件和使用的库的 jar 包,分别放在 WEB-INF/classes 和 WEB-INF/lib 目录下面。多个应用共享的 Java 类文件和 jar 包,分别放在 Web 容器指定的由所有 Web 应用共享的目录下面。当出现找不到类的错误时,检查当前类的类加载器和当前线程的上下文类加载器是否正确。

http://agapple.iteyeeye.com/blog/826661

容器

jboss(4.05)

tomcat(6.0.30)

jetty(7.1.20)

支持child/parent first设置(默认值)

Java2ClassLoadingCompliance=false

delegate=false

_parentLoaderPriority=false

过滤package配置

FilteredPacages

默认值: javax.servlet,org.apache.commons.logging

packageTriggers

默认配置:org.apache.commons.logging

systemClasses

默认配置:java.

javax.

org.xml.

org.w3c.

org.apache.commons.logging.

org.eclipse.jetty.continuation.

org.eclipse.jetty.jndi.

org.eclipse.jetty.plus.jaas.

org.eclipse.jetty.websocket.

org.eclipse.jetty.servlet.DefaultServlet.

特殊性

1. UseJBossWebLoader=false时,过滤packages才能生效

2. UseJBossWebLoader=true时,不支持过滤packages

3. jboss 5.0以后UseJBossWebLoader参数将不支持

1. 在执行child/parent判断之前,会委托system classloader装载系统class,比如jdk的lib库

1. 多了一个serverclass配置,如果是serverclass优先采用child first

2. systemclass默认的配置,多了javax,org.xml,org.w3c配置。

相关文档

svn url : http://anonsvn.jboss.org/repos/jbossas/tags/JBoss_4_0_5_GA_CP18

jboss社区classloader文档: http://community.jboss.org/wiki/ClassLoadingConfiguration

svn url : http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk

官方classloader机制: http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

svn url : http://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/tags/jetty-7.2.0.v20101020/

classloader 官方文档: http://docs.codehaus.org/display/JETTY/Classloading

静态字段

http://stackoverflow.com/questions/797964/what-is-the-exact-meaning-of-static-fields-in-java

Static doesn't quite mean "shared by all instances" - it means "not related to a particular instance at all". In other words, you could get at the static field in class A without ever creating any instances.

As for running two programs within the same JVM - it really depends on exactly what you mean by "running two programs". The static field is effectively associated with the class object, which is in turn associated with a classloader. So if these two programs use separate classloader instances, you'll have two independent static variables. If they both use the same classloader, then there'll only be one so they'll see each other's changes.

As for an alternative - there are various options. One is to pass the reference to the "shared" object to the constructor of each object you create which needs it. It will then need to store that reference for later. This can be a bit of a pain and suck up a bit more memory than a static approach, but it does make for easy testability.

这个不知出处,但根据java规范,静态字段是在类加载器加载类时初始化的,也证明了上面的说法。

一般的java程序,每次启动也是单独的classloader实例,所以即使同一个类的main方法同时执行多次,也不会互相干扰。

总结发言,静态字段虽然是依附于classloader,在web容器下每个app又是自己的classloader,客观来说不会存在互相影响的问题,但任然存在这个风险。所以能不用就不用,特别是是对于单例模式。

 


Total views.

© 2013 - 2018. All rights reserved.

Powered by Hydejack v6.6.1