Hoe een onbevredigd Rinkerror (kan geen afhankelijke bibliotheken vinden) in een JNI-project

Ik werk aan een Java-project dat de JNI gebruikt. De JNI noemt een aangepaste bibliotheek die ik mezelf heb geschreven, laten we zeggen mylib.dll en dat afhankelijk is van een 3e party-bibliotheek, libsdfile-1.dll.

Wanneer ik mijn programma voer, crasht het met

java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.

Ik heb deze site (en anderen) gezocht en ik heb een aantal fixes geprobeerd:

  1. Ik lieerde afhankelijkheidswalker. DW gaf een paar waarschuwingen – dat twee bibliotheken vereist door libsbdfile, mpr.dll en shlwapi.dll, hadden “onopgeloste import” – maar de DW FAQ zei dat deze waarschuwingen veilig kunnen worden genegeerd.

  2. Ik heb de methode-namen in Mylib.dll opgelost, zoals gesuggereerd hier . De methode-namen hadden op de een of andere manier verknoeid door de compiler, maar ik voegde Linker-vlaggen toe en de DLL-methode-namen komen nu overeen met die in mijn JNI Header-bestand precies.

  3. Ik heb al deze DLL’s in dezelfde map ingelegd – dezelfde map als de .jar die ze noemt – om ervoor te zorgen dat ze op het juiste pad staan.

Geen dobbelstenen.

Heeft iemand enig idee wat er aan de hand is?

Ik doe mijn ontwikkeling in Visual Studio 2010 op een MacBook Pro (via parallels). Ik doe mijn test in Windows XP op een Toshiba-laptop.


1, Autoriteit 100%

Ik ben er vrij zeker van dat het klassenpad en het gedeelde bibliotheekzoekpad weinig met elkaar te maken hebben. Volgens Het JNI-boek (dat weliswaar Is oud), op Windows Als u de java.library.pathSystem Property niet gebruikt, moet de DLL in de huidige werkdirectory zijn of in een directory in de Windows PATHMilieuvariabele.


update:

Lijkt op Oracle heeft de PDF verwijderd van de website. Ik heb de bovenstaande link bijgewerkt om naar een exemplaar van de PDF te wonen aan de Universiteit van Texas – Arlington.

Ook kunt u ook de HTML-versie van Oracle lezen van de JNI-specificatie . Dat woont in het Java 8-gedeelte van de Java-website en zo zal hopelijk een tijdje in de buurt zijn.


update 2:

Tenminste in Java 8 (ik heb geen eerdere versies gecontroleerd) U kunt doen:

java -XshowSettings:properties -version

om het Shared Library Search Path te vinden. Zoek naar de waarde van de java.library.patheigenschap in die output.


2, Autoriteit 36%

Ik wil dit interessante geval informeren, na alle bovenstaande methoden geprobeerd te hebben, is de fout er nog steeds. Het rare is dat het werkt op een Windows 7-computer, maar op Windows XP niet. Dan gebruik ik afhankelijkheidswandelaar en ontdekte dat er op Windows XP geen VC++ Runtime is als mijn dll-vereiste. Na het installeren van het VC++ Runtime-pakket hierwerkt het als een tierelier . Wat me stoorde, is dat hij steeds zegt Kan geen afhankelijke bibliotheken vinden, terwijl intuïtief de JNI-afhankelijke dll aanwezig is, maar uiteindelijk blijkt dat de JNI-afhankelijke dll een andere afhankelijke dl vereist. Ik hoop dat dit helpt.


Antwoord 3, autoriteit 29%

U moet uw JNI-bibliotheek laden.

System.loadLibrarylaadt de DLL van het JVM-pad (JDK bin-pad).

Als je een expliciet bestand met een pad wilt laden, gebruik je System. laden()

Zie ook: Verschil tussen System.load() en System.loadLibrary in Java


Antwoord 4, autoriteit 14%

Als u een 32-bits versie van uw dll laadt met een 64-bits JRE, kunt u dit probleem krijgen. Dit was mijn geval.


Antwoord 5, autoriteit 11%

Controleer of uw bibliotheekpad juist is of niet. Natuurlijk kunt u de volgende code gebruiken om uw bibliotheekpadpad te controleren:
System.out.println(System.getProperty("java.library.path"));

U kunt het java.library.pathaanwijzen wanneer u een Java-toepassing start:

java -Djava.library.path=path ...

6, Autoriteit 11%

had identiek probleem met op XP-machine bij het installeren van javacven opencvin combinatie met Eclipse. Het bleek dat ik de volgende bestanden miste:

  • MSVCP100.DLL
  • MSVCRR100.DLL

Zodra deze zijn geïnstalleerd, heeft het project gecompileerd en liep OK.


7, Autoriteit 4%

  • Kort antwoord: voor “kan geen afhankelijke bibliotheek” -fout vinden, controleert u uw $ pad (komt overeen met bullet punt # 3 hieronder)
  • Long Antwoord:
    1. Pure Java World: JVM gebruikt “ClassPath” om klasbestanden te vinden
    2. JNI World (Java / Native Boundary): JVM gebruikt “java.library.path” (die standaard naar $ pad is) om DLL’s
    3. te vinden

    4. Pure Native World: Native Code gebruikt $ PATH om andere DLL’s
    5. te laden


8, Autoriteit 4%

Ik heb een geweldig artikel gevonden door een paar vrienden in Keepsafe dat door hetzelfde ging. Het werkte voor mij, dus hopelijk helpt het je ook! Heb gelezen als je geïnteresseerd bent (De gevaren van het laden van inheemse bibliotheken op Android ) of gebruik gewoon

compile 'com.getkeepsafe.relinker:relinker:1.2.3'

en vervang

System.loadLibrary("myLibrary");

met

ReLinker.loadLibrary(context, "mylibrary");

9, Autoriteit 2%

Ik had altijd precies hetzelfde probleem en eindelijk werd het opgelost.

Ik plaats alle afhankelijke DLL’s in dezelfde map waar mylib.dll was opgeslagen en zorg ervoor dat de JAVA-compiler deze kan vinden (als er geen mylib.dll in het compilatiepad staat, zou er een fout zijn die dit meldt tijdens het compileren ). Het belangrijkste dat u moet opmerken, is dat u ervoor moet zorgen dat alle afhankelijke bibliotheken van dezelfde versie zijn met mylib.dll, bijvoorbeeld als uw mylib.dll een releaseversie is, moet u ook de releaseversie van al zijn afhankelijke libs daar plaatsen .

Ik hoop dat dit anderen kan helpen die hetzelfde probleem hebben ondervonden.


Antwoord 10, autoriteit 2%

Ik had hetzelfde probleem en ik heb alles geprobeerd wat hier is gepost om het op te lossen, maar niets werkte voor mij.
In mijn geval gebruik ik Cygwin om de dll te compileren. Het lijkt erop dat JVM de JRE DLL’s probeert te vinden in het virtuele Cygwin-pad.
Ik heb het virtuele mappad van Cygwin toegevoegd aan de DLL’s van JRE en het werkt nu.
Ik deed zoiets als:

SET PATH=”/cygdrive/c/Program Files/Java/jdk1.8.0_45″;%PATH%


Antwoord 11, autoriteit 2%

In mijn situatie probeerde ik een Java-webservice in Tomcat 7 uit te voeren via een connector in Eclipse. De app werkte goed toen ik het oorlogsbestand implementeerde naar een exemplaar van Tomcat 7 op mijn laptop. De app vereist een jdbc type 2-stuurprogramma voor “IBM DB2 9.5”. Om de een of andere vreemde reden kon de connector in Eclipe de paden in de IBM DB2-omgevingsvariabelen niet zien of gebruiken om de dll-bestanden te bereiken die op mijn laptop waren geïnstalleerd als de jcc-client. In de foutmelding stond dat het het db2jcct2 dll-bestand niet kon vinden of dat het de afhankelijke bibliotheken voor dat dll-bestand niet kon vinden. Uiteindelijk heb ik de connector verwijderd en opnieuw opgebouwd. Toen werkte het naar behoren. Ik voeg deze oplossing hier toe als documentatie, omdat ik deze specifieke oplossing nergens anders heb kunnen vinden.


Antwoord 12, autoriteit 2%

Bij het aanroepen van System.loadLibrary(), de JVM zal zien op de java.library.pathvoor je eigen bibliotheek. Echter, als dat native library enige afhankelijkheden van andere inheemse bibliotheken verklaart, dan is het besturingssysteem zal worden belast met het vinden van die native library afhankelijkheden.

Sinds het besturingssysteem heeft geen concept van de java.library.path, het zal geen mappen die u op de java.library.path plaatsen te zien. In plaats daarvan zal het alleen zoeken in de mappen op PATH omgevingsvariabele van het besturingssysteem. Dit is helemaal prima als de native library afhankelijkheid is een besturingssysteem native library, omdat het zal worden gevonden op het pad. Echter, als de native library afhankelijkheid is een native library die u of iemand anders gemaakt, dan zal het niet worden gevonden op de weg, tenzij je het plaatst daar. Dit gedrag is vreemd, onverwacht, en niet goed gedocumenteerd, maar het is gedocumenteerd in de OpenJDK issue tracker hier . U vindt er ook een andere StackOverflow antwoord versterking van deze verklaring, hier .

Dus, heb je een paar opties. Je kan ofwel te laden elk native library in de juiste afhankelijkheid met behulp van System.loadLibrary(), of u kunt het pad wijzigen om de mappen waar uw moedertaal bibliotheken worden opgeslagen op te nemen.


13

Het creëren van statische bibliotheek voor mij werkte, samenstellen met g++ -static. Het bundelt de afhankelijke bibliotheken samen met het bouwen.


14

het installeren van Microsoft Visual C++ 2010 SP1 Redistributable Vast IT


15

plaats de vereiste DLL’s in de map en stel het pad in PATH omgeving.
zorg ervoor dat bijgewerkte milieu PATH variabele wordt gereflecteerd.


16

Ik was tegengesteld met hetzelfde probleem met FFMPEG-bibliotheek na het samenvoegen van twee Android-projecten als één project.

Eigenlijk kwestie aankwam vanwege twee verschillende versies van FFMPEG-bibliotheek, maar ze waren geladen met dezelfde namen in het geheugen. Eén bibliotheek werd in Jnilibs geplaatst terwijl andere in een andere bibliotheek was die als module werd gebruikt. Ik was niet in staat om de modulecode aan te passen omdat het opnieuw was, dus ik heb de gebruikte in mijn eigen code aan FFMPEGCamera en laadde het in het geheugen met dezelfde naam.

System.loadLibrary("ffmpegCamera");

Dit is het probleem opgelost en nu laden beide versies van bibliotheken goed als afzonderlijke naam en proces-ID in het geheugen.

Other episodes