java - Programmet bruger forældet (ikke nuværende) env-variabelværdi

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et C ++-program, der internt bruger java (via min C ++ dll, der indpakker WebLogic jsmc.dll, der internt bruger jvm.dll).


Når jeg indstiller CLASSPATH før du kører mit program, findes alle JAR-biblioteker, og programmet fungerer korrekt.
Når jeg ikke indstiller CLASSPATH før du kører mit program, er JAR'erne ikke fundet, hvilket naturligvis forventes.


Nu, når jeg indstiller CLASSPATH før du kører mit program, men ryd denne CLASSPATH miljøvariabel inden for programkoden før indlæser min dll, der bruger java, sker der en mærkelig ting: alle JAR'er findes stadig, og programmet fungerer som om alt var OK. Jeg har verificeret på flere måder, at CLASSPATH virkelig er slettet fra env-variablerne (for eksempel ved at bruge ProcessExplorer eller ved at udskrive dens værdi).


SPØRGSMÅL:


Kan du forklare denne adfærd for mig? Jeg ikke undrer mig over, hvorfor java ignorerer CLASSPATH'en jeg sætter, men hvordan er det muligt at java ser den gamle CLASSPATH-værdi, ikke den nuværende? Jeg understreger, at det ikke er 'Det er ikke muligt for java at gemme den gamle CLASSPATH-værdi på en eller anden måde, fordi Java ikke blev indlæst på det tidspunkt, hvor den gamle værdi var tilgængelig.


Hvordan kan jeg gøre java til at respektere ændringerne i processen env-variabler?


DETALJER:


Problemet ovenfor er bare en forenkling, jeg har lavet for at undersøge mit virkelige problem. Jeg forsøger at indstille CLASSPATH fra programmet og undgå at få det sat eksternt. Men java bruger den eksternt indstillede CLASSPATH, ikke den, jeg satte ind i programmet.


Jeg læser og indstiller værdierne for env-variabler ved hjælp af Windows API (GetEnvironmentVariableA, SetEnvironmentVariableA). Jeg har verificeret, at programprocessens miljøvariabler virkelig ændrer sig efter at have indstillet dem på denne måde. Jeg har endda udskrevet CLASSPATH-værdien fra den dll, der bruger java, før du kalder en java-metode. Jeg kontrollerede ved hjælp af ProcessMonitor at jvm.dll er rigtig indlæst efter CLASSPATH slettes. Jeg har også forsøgt at udelukke muligheden for at CLASSPATH læses fra moderprocessen. Nu er jeg ganske sikker på at på det tidspunkt, hvor jvm.dll bliver lastet, er CLASSPATH allerede slettet fra procesmiljøet.


Jeg har prøvet både et Visual C ++ 2010 testprogram og HP LoadRunner C-compiler (mmdrv.exe) vuser script, med det samme resultat. LoadRunner er hovedårsagen til, at jeg har brug for at løse dette problem.

Bedste reference


Problemet skyldtes, at C-runtime på en eller anden måde caches miljøvariablerne. Mens jeg forsøgte at ændre CLASSPATH ved hjælp af systemfunktionen SetEnvironmentVariableA (), læste jmsc.dll CLASSPATH fra C-runtime cachen. C-runtime forsøger at synkronisere cachen med de reelle værdier i procesmiljøet, men åbenbart ikke særlig succesfuldt. Det var nødvendigt for mig at erstatte systemopkaldet til SetEnvironmentVariableA () med opkaldet til \_putenv () fra C-runtime for at ændre CLASSPATH.


Men der var et andet problem. Der var forskellige versioner af C-runtime, der blev brugt af min kode, hver med deres eget miljøcache. Min VC-kode blev knyttet til msvcr100.dll, mens jmsc.dll (der instanser Java VM) bruger msvcrt.dll. Løsningen var at forbinde min kode til msvcrt.dll også, så min kode angiver CLASSPATH ved hjælp af \_putenv () fra samme C-runtime, som jmsc.dll læser.


Takket være Harry Johnston til det afgørende tip, og Peter Cetinski for værdifuld information.

Andre referencer 1


Du bør ikke stole på CLASSPATHs miljøvariabel, når du påberåber en ny JVM-proces fra C ++. JNI-grænsefladen giver en mekanisme til at specificere klassepaden af ​​JVM ved opstart.


Se http://java.sun.com/docs/books/jni/html/invoke.html#28719[1]