# Native Library My.dll already loaded in another classloader



## syska (16. August 2006)

Hallo zusammen,

wenn ich innerhalb eines static-Konstruktor eine C++/COM-Dll (My.dll) mit Hilfe der Funktion System.loadLibrary("My") lade, dann klappt das wunderbar.


```
public class MyClass
{
         static
         {
                 System.loadLibrary("My");
         }
}
```

Allerdings wird durch ein bestimmtes Eclipse-Plugin (JasperAssistent) die Klasse bzw. der Konstrukor mehrmals ausgeführt und so kommt es zu folgendem Fehler:
*Native Library C:\Programme\Eclipse\My.dll already loaded in another classloader*

Nun würde ich gerne das Problem an der Wurzel packen und unabhängig von irgendwelchen Plugins etc. prüfen, ob My.dll *bereits* geladen wurde oder nicht, um entsprechend reagieren zu können. Gibt es hierfür eine Möglichkeit ?  

Also sowas wie ...

```
static
{
      if( !isLibraryAlreadyLoaded("My") )
              System.loadLibrary("My");
}
```

Schonmal vielen Dank
Chris


----------



## Thomas Darimont (16. August 2006)

Hallo!

Eine Möglichkeit wäre es den Ladestatus der Library in einem statischen Klassenattribut zu halten. Das ist nur Problemetisch wenn es wegen der Verwendung von mehreren ClassLoadern mehrere Instanzen dieser Class-Klasse gibt...
Eine andere Möglichkeit wäre beispielsweise die den Ladestatus in einem System.Property zu vermerken... System.setProperty("LIBRARY_XX_LOADED", Boolean.TRUE.toString()); was aber auch nich so schick ist, da jeder beliebige Code mit entsprechender Permission die Umgebungsvariablen modifizieren darf...
Du könntest den Ladestatus aber auch direkt an einem property deines Plugins vermerken und dann entsprechend Abfragen...

Gruß Tom


----------



## syska (17. August 2006)

Hi Tom,

erstmal vielen Dank für Deine schnelle und kompetente Antwort  

Die "setProperty"-Variante klappt Prima, auch über mehrere Instanzen hinaus aber jetzt kommt der Hammer !

Java verbietet das zweimalige Laden einer Library, jedoch sind die Funktionen der geladenen Native-Klasse nur dem ClassLoader zugänglich der diese auch geladen hat  

Das heisst, bei dem 2. Versuch My.dll zu laden greift meine If-Abfrage korrekt und diese wird nicht geladen, jedoch bekomme ich beim Verwenden der Native-Funktionen einen "java.lang.UnsatisfiedLinkError"-Error, obwohl My.dll bereits geladen wurde.

Die entsprechende Helper-Klasse ...

```
public final class NativeHelper
{
	private static final String PROP_NAME = "OFCKWRAPPER_LOADED";
	
	public static void setLibLoadStatus( boolean status )
	{
		if( status )
			System.setProperty(PROP_NAME, Boolean.TRUE.toString());
		else
			System.setProperty(PROP_NAME, Boolean.FALSE.toString());
	}
	
	public static boolean getLibLoadStatus()
	{
		String sValue = System.getProperty(PROP_NAME);
		if( (sValue != null) && (sValue.equalsIgnoreCase(Boolean.TRUE.toString())) )
			return true;
		else
			return false;
	}
}
```

und hier der neue static-Konstruktor

```
static
	{		
		if( !NativeHelper.getLibLoadStatus() )
		{
			System.loadLibrary("My");
			NativeHelper.setLibLoadStatus(true);
		}
	}
```

Sieht so aus als hätte ich schlechte Karten oder fällt Dir bzw. Euch noch was ein oder auf ?


----------



## Thomas Darimont (17. August 2006)

Hallo!

Eine andere Möglichkeit wäre auch die, dass du deine Dll einfach in dem Manifest.MF File deines Bundles mittels des
Bundle-NativeCode: abcdef.dll deklarierst... dann wird deine DLL vom OSGi Framework geladen. Damit die dll so gefunden wird, muss sie auch ins Bundle-Root legen.

Gruß Tom


----------



## syska (17. August 2006)

Bis Manifest hab ich´s verstanden ... 

Hättest Du ein Beispiel wie die Zeile in der Manifest-Datei auszusehen hätte ?


----------



## Thomas Darimont (17. August 2006)

Hallo!

Im Hyades Plugin Manifest findet man beispielsweise folgendes:

```
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %PLUGIN_NAME
Bundle-SymbolicName: org.eclipse.hyades.execution.win32.x86;singleton:=true
Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86))
Bundle-Version: 4.2.0.v200606131519
Bundle-Vendor: %PROVIDER_NAME
Fragment-Host: org.eclipse.hyades.execution;bundle-version="[4.2.0,5.0.0)"
Bundle-Localization: plugin
Bundle-NativeCode: tptpCommon.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 tptpNP.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 tptpShm.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 CommonBaseEvent.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hcbnd.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hcclco.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hccldt.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hccls.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hcclsm.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hcjbnd.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 hclaunch.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003",
 piAgent.dll;processor="x86";osname="WindowsXP";osname="Windows2000";osname="Windows2003";osname="Windows Server 2003"
```

Gruß Tom


----------

