影响第三方库使用的类加载器

时间:2013-10-23 16:19:22

标签: java classloader resourcebundle

我必须依赖第三方库,它希望某些事情在类路径中。好像用了

ResourceBundle.getBundle("cmbcmenv");

获取属性文件。此文件的位置由安装连接器时设置的环境变量指定(它创建一个指向包含该文件的目录的变量“IBMCMROOT”)。我不能在类路径中使用相对路径或绝对路径,因为连接器的安装目录可能会有所不同。

我尝试过像这样手动添加新的ClassLoader:

ClassLoader defaultLoader = Thread.currentThread().getContextClassLoader();     
        String config = System.getenv().get("IBMCMROOT")+"/cmgmt";      
        URLClassLoader loader = URLClassLoader.newInstance(new URL[]{new File(config).toURI().toURL()},defaultLoader);
        Thread.currentThread().setContextClassLoader(loader);           

getBundle也失败了。由于它是第三方库,我不能使用

ResourceBundle.getBundle("cmbcmenv",Locale.getDefault(),loader);

否则不会有这个问题..

如何强制ResourceBundle使用特定的ClassLoader?似乎getBundle使用CallerClassloader或SystemClassloader但是没有办法影响它,对吧?

1 个答案:

答案 0 :(得分:1)

您可以欺骗ResourceBundle类使用与用于密钥中实际查找的ClassLoader不同的ResourceBundle rb=ResourceBundle.getBundle("Resources", new ResourceBundle.Control() { @Override public long getTimeToLive(String baseName, Locale locale) { return Long.MAX_VALUE; } @Override public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { return super.newBundle(baseName, locale, format, defaultLoader, reload); } }); 来缓存捆绑包实例。

getBundle

请注意,ClassLoader调用使用的是默认的SystemClassLoader(或调用者ClassLoader),因为没有指定类加载器。这是用于缓存结果的密钥中使用的Control。但是,在查找真实捆绑包时,自定义ClassLoader实施会将defaultLoader替换为您的ResourceBundle实例。

请注意,您应该在第三方库的查找操作之前执行此操作。此控件表示bundle永远不会过期,但当JVM内存不足时,它仍可能被释放。

请注意,{{1}}也会缓存失败,因此在其他人尝试查找该捆绑包之前,必须 这个技巧。