2010-01-12 44 views
2

我想启动一个java子进程,它具有与当前java进程相同的java classpath和动态加载的类。以下是不够的,因为它不包含任何动态加载的类:使用父进程启动Java子进程类路径

String classpath = System.getProperty("java.class.path"); 

目前我在寻找与下面的代码所需要的每个类。但是,在某些机器上,某些类/库会失败,源变量为空。是否有更可靠和更简单的方法来获取当前jvm进程使用的库的位置?

String stax  = ClassFinder.classPath("javax.xml.stream.Location"); 

public static String classPath(String qualifiedClassName) throws NotFoundException { 
    try { 
     Class qc = Class.forName(qualifiedClassName); 
     CodeSource source = qc.getProtectionDomain().getCodeSource(); 
     if (source != null) { 
      URL location = source.getLocation();   
      String f = location.getPath(); 
      f = URLDecoder.decode(f, "UTF-8"); // decode URL to avoid spaces being replaced by %20 
      return f.substring(1); 
     } else { 
      throw new ClassFinder().new NotFoundException(qualifiedClassName+" (unknown source, likely rt.jar)"); 
     } 
    } catch (Exception e) { 
     throw new ClassFinder().new NotFoundException(qualifiedClassName); 
    } 
} 
+0

出于好奇:你是怎么想出这种方法的? – 2010-01-12 16:24:55

+0

我是怎么想出这种方法的?我发现它在网上的某个地方,不记得现在在哪里。 我认为这个问题真的归结为,为什么ProtectionDomain .getCodeSource()有时返回null。 APIs文档没有用,他们只是说该方法可能会返回null。 – 2010-01-12 17:15:40

回答

1

我想启动一个java子进程,它具有与当前java进程相同的java classpath和动态加载的类。

你的意思是调用一个新的JVM?

鉴于...

  • 有可能在各种代理程序和工具来插入,可以在加载时变换班JVM
  • 有可能采取byte阵列和转它变成一个类
  • 有可能具有复杂的类装载程序层次结构具有不同类之间的可见性,并且具有相同的类装载多次

......没有一般的,魔术的,万能的和万无一失的方式来做到这一点。你应该设计你的应用程序和它的类加载机制来实现这个目标。如果您允许使用第三方插件,则必须记录其工作原理以及他们如何注册库。

+0

最后,我使用上面描述的机制来查找我们的库。我们的库引用清单中的所有其他库,我知道它们将安装在与库相同的文件夹中。 – 2010-01-14 22:12:51

2

请参阅我的previous question其中包括获取类路径以及如何启动子流程。

+0

确实 - 这是一个类似的问题。我需要的是额外的动态加载类。我不想用这些文件定义一个额外的文件,或者引入额外的环境变量来定位它们,因为它们都是由当前环境'知道的'。 – 2010-01-12 17:01:05

0

如果你看一下Class.getClassLoader的javadoc,你会发现“bootstrap”类加载器通常表示为null。 “String.class.getClassLoader()”将在普通的sun jvm实现上返回null。我认为这个实现细节会传递到CodeSource中。因此,只要您的子进程使用与当前进程相同的jvm impl,我就不会想象您需要担心来自引导类加载器的任何类。