jacob memory leak

arglofou

Grünschnabel
Hallo,

ich hoffe, mir kann jemand beim einem Speicherproblem mit jacob (JavaCOMBridge) helfen.
In beiden folgenden Faellen laeuft meine Anwendung irgendwann „OutOfMemory“.
Vielleicht muss jacob auf bestimmte Weise initialisiert werden?

-----------------------
while( true )
{
ActiveXComponent _systemControllerProxy = new ActiveXComponent( “String representation of the COM object” );
_systemControllerProxy.invoke( “a method of the COM object” );
_systemControllerProxy.safeRelease();
}
-----------------------
Das safeRelease() scheint hierbei nicht auszureichen, den reservierten Speicher wieder frei zu geben.

Eigentlich moechte ich den Code so ausfuehren, aber hier ist der Speicherverbrauch noch dramatischer (es scheint bei jedem invoke() neue Objekte angelegt zu werden, obwohl nur mit ein und denselben gearbeitet werden soll:

-----------------------
ActiveXComponent _systemControllerProxy = new ActiveXComponent( “String representation of the COM object” );
while( true )
{
_systemControllerProxy.invoke( “a method of the COM object” );
}

_systemControllerProxy.safeRelease();
ComThread.Release();
-----------------------

Bin fuer jede Hilfe dankbar.
Viele Gruesse,
Andreas



Das folgende Code-Schnipsel nur mit einem Variant-Objekt laeuft in einer Endlos-Schleife z.B. nur dann nicht OutOfMemory, wenn die ComThread.Release()-Methode aufgerufen wird:

public static void variantMemLeakTest()
{
System.out.println("variantMemLeakTest(): starting ...");
Variant l_variant = new Variant();
l_variant.safeRelease();
//ComThread.Release();
System.out.println("variantMemLeakTest(): finished.");
}
 
Hi,
also als aller erstes, solltest du bitte [code=java][/code]-Tags benutzen, damit der Code gehighlited wird.
Dann solltest du in deinem Code dringenst vermeiden, while(true)-Schleifen zu verwenden. Außer du baust in der while-Schleife noch einen Thread.sleep(...) ein. Aber auch das ist nicht wirklich günstig, da es keine Abbruchbedingung für die Schleife gibt. Dadurch wird die OutOfMemory-Exception schnell ausgelöst.

Gruß

Fabio
 
Ganz einfach: du erzeugst in einer Endlosschleife neue Objekte, das gibt zwangsläufig ein Speicherproblem.
Welchen Zweck hat diese Endlosschleife? ich kann das nicht verstehen...
 
Hallo Fabio,

danke fuer die schnelle Antwort und die Hinweise, bin noch neu hier.

Die while-Schleifen haben nur Beispiel-Charakter, um das Problem vereinfacht darzustellen und mir im Prozess-Explorer den Speicherverbrauch schnell anzuzeigen.

Eigentlich lege ich mir das ActiveXComponent einmalig zur Laufzeit an und moechte es moeglichst "fuer immer" benutzen.
Im normalen Einsatz habe ich keine Endlosschleife.
Damit wollte ich das Problem nur viel schneller sichtbar machen, was sonst mehrer Tage dauert.

Gruss,
Andreas
 
prinzipiell ist es so, dass die JVM eine automatische Speicherbereinigung durchführt, sobald Speicher knapp ist. Allerdings funktioniert diese Speicherbereinigung nur für Java-Objekte. Die ActiveX-API und wahrscheinlich auch Teile von jacob sind in C/C++ geschrieben, auf diesen nativen Code hat die JVM keinen Einfluss, daher kann sie auch keine Speicherbereinigung im Speicherbereich des nativen Codes durchführen. Da du trotzdem Speicherprobleme hast, ist wahrscheinlich die ActiveX-API und/oder jacob schlecht programmiert.
Aber warum sollte man eine ActiveX-Anwendung mehrere Tage oder gar Wochen ununterbrochen laufen lassen?
PS: So lange hält wahrscheinlich nicht mal dein Browser durch – ich kann mir kaum vorstellen, dass der nicht auch ein Memory Leak hat.
 
Was ich hier komisch finde , auch wenn es nur ein Beispiel ist , wie du auf sowas kommst :
Java:
while(true)
{
//to-do something
}
release()
Mal davon abgesehen das du sowas garnicht compilen kannst *javac wird hier ein "unreachable statement" bemängeln* würde ich dann gerne mal wissen wie du ren logisch auf die Anahme kommst das irgendwas nach eine endlos-Schleife noch ausgeführt werden könnte ?
 
Hi,

der Code soll in einem Produktionsumfeld moeglichst viele Tage lang laufen koennen.

Jacob bietet mir die bequemste Moeglichkeit, aus meinem Java-Framework auf den C++-Code des Systems zuzugreifen, das ich kontrollieren moechte, ohne mich selbst um JNI oder JNA-Overhead zu kuemmern.

Momentan bin ich noch nicht sicher, ob ich jacob falsch benutze oder ob es fuer meine Zwecke ungeeignet ist.

Gruss,
Andreas
 
Hallo,

Ich selbst benutze Jacob, und habe keine Probleme damit.

Mit dem Milestone 4 Release wurde ein Speicherleck behoben (ich weiß jedoch nicht welches).
Hast du dir eigentlich die Dokumentation zu Jacob durchgelesen und probiert?

Ich mache das Ganze in etwa so:

Java:
ComThread.InitMTA(true);
System.out.println(LoggingUtils.getTimeString() + "COM Thread launched");

ActiveXComponent borealisCom = new ActiveXComponent("AuroraB.Application");
System.out.println(LoggingUtils.getTimeString() + "Hooked into Aurora Borealis");

Dispatch borealisController = (Dispatch) borealisCom.getObject();

// Ab hier mit dem Controller arbeiten, von mir aus in einer Endlosschleife:

while(true){
	Variant version = Dispatch.call(borealisController, "Version");
	System.out.println(LoggingUtils.getTimeString() + "Version of Aurora Borealis is: " + version.getString());

	Variant hres = Dispatch.call(borealisController, "DoorTest");
	System.out.println(LoggingUtils.getTimeString() + "Is sliding door operating as expected?: " + hres.getBoolean());

	if(someCondition){
		break;
	}
}
// Nach Beenden der Operationen über COM

ComThread.Release();
ComThread.quitMainSTA();
System.out.println(LoggingUtils.getTimeString() + "Released COM Thread");

Es ist jetzt egal, wie viele Variant / Dispatch Objekte ich erstelle.
Sobald keine Referenzen auf das Java Objekt (mit Ausnahme der Referenz von Jacob) vorliegen, löscht Jacob auch das native Pendant aus der ROT (Running Object Table), und anschließend kümmert sich der Java Garbage Collector um den Rest.

Warum es bei dir nicht klappt, weiß ich nicht.

Zu meinem Beispiel: Wichtig ist, dass die Releasemethoden am Schluss IMMER ausgeführt werden, da so manches in einem inkonsistenten Zustand gelassen werden kann. (finally block benutzen, oder ähnlich).
Zu beachten ist, dass nach dem Release des Threads der Zugriff auf zuvor erstellte Components verloren geht.

mfg,
Martin
 
Zuletzt bearbeitet:
Hallo Martin,

dankeschoen fuer deine Tipps.
Ja, die Dokus zu jacob habe ich mir durchgelesen.
Nach der Milestone 4 Release will ich noch einmal schauen, ich hatte mir eigentlich eine neue Version heruntergeladen.

Wie sieht denn dein Speicherverbrauch waehrend der while-Schleife in deinem Code-Schnipsel aus?

In meinen Testfaellen (inklusive ComThread.InitMTA( true ) und ComThread.quitMainSTA() ) konnte ich das Speicherleck nur dann umgehen, wenn ich die Release-Methoden ausgefuehrt hatte. Natuerlich verliere ich dann die COM-Objekte und muss die Verbindung wieder neu erstellen, was ich vermeiden wollte.

Gruss,
Andreas
 

Neue Beiträge

Zurück