2012-03-09 73 views
1

我有一个内部使用java的C++程序(通过我的C++ dll包装了内部使用jvm.dll的WebLogic jsmc.dll)。程序使用过时的(不是当前的)env变量值

当我在运行我的程序之前设置CLASSPATH时,找到所有JAR库并且程序正常工作。 当我做不是设置CLASSPATH之前运行我的程序,JARs是而不是发现,这当然是预期的。

现在,当我设置运行我的程序前的CLASSPATH,但明确程序代码这里面CLASSPATH环境变量之前加载我的DLL使用Java,奇怪的事情发生了:所有的JAR仍然发现,程序就好像一切正​​常一样。我通过几种方式验证了CLASSPATH实际上是从env变量中删除的(例如通过使用ProcessExplorer或打印它的值)。

问题:

你能向我解释这种行为吗?我是不是想知道为什么java忽略我设置的CLASSPATH,但是怎么可能 java看到旧的CLASSPATH值,而不是当前的值?我强调,java不可能以某种方式存储旧的CLASSPATH值,因为在旧值可用时未加载java。

我该如何让java尊重过程env变量中的更改?

详情:

上述的问题只是我做了探索我真正的问题简单化。我试图从程序中设置CLASSPATH,并避免将它设置在外部。但是java使用了外部设置的CLASSPATH,而不是我在程序中设置的CLASSPATH。

我使用Windows API(GetEnvironmentVariableA,SetEnvironmentVariableA)读取和设置env变量值。我已经验证过,通过这种方式设置它们后,程序过程环境变量确实发生了变化我甚至在调用任何java方法之前,从使用java的dll打印CLASSPATH值。我使用ProcessMonitor检查了jvm.dll真的被加载之后 CLASSPATH被删除。我也试图排除从父进程读取CLASSPATH的可能性。现在我非常确定在加载jvm.dll时,CLASSPATH已经从进程环境中删除。

我已经尝试了Visual C++ 2010测试程序和HP LoadRunner C编译器(mmdrv.exe)vuser脚本,结果相同。 LoadRunner是我需要解决这个问题的主要原因。

+0

您是否已经仔细检查了所使用的CLASSPATH只能来自父进程(例如命令shell)而不是来自例如存储在注册表中的默认环境变量值? – 2012-03-10 05:06:47

+0

我设法让代码在Visual Studio中工作。将“jmsc.dll”标记为延迟加载(属性 - >链接器 - >输入 - >延迟加载的Dll =“jmsc.dll”)就足够了。 不幸的是,相同的代码与LoadRunner的工作方式不一样 - 即使dll是懒洋洋地加载的,加载的dll仍然使用原始的CLASSPATH,而不是修改过的。 : - (((可能在执行lr_load_dll()时出现一些怪癖) – xarx 2012-03-12 14:23:33

+0

一个可能的解释是,jmsc.dll中包含或引用的C运行时可能在启动时自己创建了环境变量副本。确定它们在jvm.dll中的结果如何:或许它使用相同的运行时,或者jmsc.dll明确地将CLASSPATH传递给jvm.dll出于某种原因,你需要用调试器来查看它以知道确定 – 2012-03-12 20:33:33

回答

1

问题是由该C-运行时莫名其妙缓存的环境变量引起的。当我尝试使用系统函数SetEnvironmentVariableA()修改CLASSPATH时,jmsc.dll从C运行时缓存读取CLASSPATH。 C运行时尝试将其缓存与流程环境中的实际值进行同步,但显然不是很成功。为了更改CLASSPATH,我需要将来自C运行时的对_putenv()的调用替换为SetEnvironmentVariableA()的系统调用。

但还有另一个问题。我的代码使用了各种版本的C运行库,每个版本都有自己的环境缓存。我的VC代码与msvcr100.dll链接,而jmsc.dll(实例化Java VM)使用msvcrt.dll。解决方案是将我的代码链接到msvcrt.dll,以便我的代码使用来自jmsc.dll读取的同一C运行时的_putenv()设置CLASSPATH。

由于哈利·约翰斯顿的重要提示,并彼得Cetinski有价值的信息。

0

从C++调用新的JVM进程时,不应该依赖CLASSPATH环境变量。 JNI接口提供了一种机制,用于在启动时指定JVM的类路径。

http://java.sun.com/docs/books/jni/html/invoke.html#28719

+0

好主意:)。但是,我没有明确创建JVM,因此我无法设置JavaVMInitArgs的参数。我只使用jmsc.dll库(用于JMS的Weblogic C-API)创建自己的JVM。如果我正确地取消了你的链接,如果我使用JNI_CreateJavaVM()创建了一个JVM,那将是一个新的JVM实例,与jmsc.dll创建的实例不同。 – xarx 2012-03-09 14:59:46

+0

你是对的,这将是一个不同的过程。我确信jmsc.dll只是调用JNI_CreateJavaVM。 – 2012-03-09 16:00:13

+0

那么,我至少应该测试在创建新的JVM和在运行之前清除类路径时会发生什么。 – xarx 2012-03-09 16:07:02

相关问题