在这种情况下将使用哪个类加载器?

时间:2012-11-16 10:25:49

标签: java multithreading classloader axis contextclassloader

我有以下问题 HashMap用于设置属性,密钥为ClassLoader 设置属性的代码如下(AxisProperties):

public static void setProperty(String propertyName, String value, boolean isDefault){  
      if(propertyName != null)  
            synchronized(propertiesCache)  
            {  
                ClassLoader classLoader = getThreadContextClassLoader();  
                HashMap properties = (HashMap)propertiesCache.get(classLoader);  
                if(value == null)  
                {  
                    if(properties != null)  
                        properties.remove(propertyName);  
                } else  
                {  
                    if(properties == null)  
                    {  
                        properties = new HashMap();  
                        propertiesCache.put(classLoader, properties);  
                    }  
                    properties.put(propertyName, new Value(value, isDefault));  
                }  
            }  
  }  

其中一个值缓存在某处,我需要重置此hashmap但问题是我不知道该怎么做。
我想加载课程(使用axis委托给URLClassLoader),但我发现代码getThreadContextClassLoader();是:{/ p>

public ClassLoader getThreadContextClassLoader()  
{  
   ClassLoader classLoader;  
        try  
        {  
            classLoader = Thread.currentThread().getContextClassLoader();  
        }  
        catch(SecurityException e)  
        {  
            classLoader = null;  
        }  
        return classLoader;  
}  

所以我认为它将使用我当前线程的类加载器而不是我用来加载类的类加载器(即axis)。
那么有办法解决这个问题吗?

注意:我已经加载axis作为我的应用程序的一部分。所以想法是通过不同的类加载器重新加载它

1 个答案:

答案 0 :(得分:1)

如果你知道有问题的类加载器,你可以在调用轴之前设置上下文类加载器:

ClassLoader key = ...;
ClassLoader oldCtx = Thread.currentThread().getContextClassLoader();
try {
  Thread.currentThread().setContextClassLoader(key);

  // your code here.
}
finally {
  Thread.currentThread().setContextClassLoader(oldCtx);
}

当您在servlet容器外部时,通常必须执行此操作,但库假定您在一个容器中。例如,您必须在OSGi容器中使用CXF执行此操作,其中未定义上下文类加载器的语义。您可以使用这样的模板来保持清洁:

public abstract class CCLTemplate<R>
{
  public R execute( ClassLoader context )
    throws Exception
 {
    ClassLoader oldCtx = Thread.currentThread().getContextClassLoader();
    try {
      Thread.currentThread().setContextClassLoader(context);

      return inContext();
    }
    finally {
      Thread.currentThread().setContextClassLoader(oldCtx);
    }
  }

  public abstract R inContext() throws Exception;
}

然后在与Axis交互时执行此操作:

ClassLoader context = ...;
new CCLTemplate<Void>() {
  public Void inContext() {
    // your code here.
    return null;
  }
}.execute(context);