Forum

Author Topic: Native dependency issue in the Java API on Ubuntu: undefined symbol: JniUtils...  (Read 609 times)

vatbub

  • Newbie
  • *
  • Posts: 1
    • View Profile
I am using the Java API  of Metashape, version 2.2.0. Everything is working fine on Windows, but when running on Linux, I am encountering something that seems like a native dependency issue. Here's a minimal code sample for demonstration (in Kotlin):

Code: [Select]
class LoadErrorDemo {
    @Test
    fun demo() {
        // Make sure this is the first time we are loading the library
        assertFalse(isMetashapeLoaded())

        System.loadLibrary("metashape") // Copied from the sample file supplied with the library

        // File contains camera data exported in the AgisoftXML format
        val demoFile =
            File("/home/six-tb-drive/Frederik/STREEM/PrismTests/V8/camera_export_from_agisoft_3_16_04_2024.xml")

        val imageFolder = File("/home/six-tb-drive/Frederik/STREEM/PrismTests/V8/ExportForAgisoft")
        val imageFiles: List<File> = imageFolder.listFiles()!!
            .filter { it.extension.lowercase() in listOf("jpg", "jpeg", "png") }

        val document = Document()
        val chunk = document.addChunk()
        chunk.addPhotos(imageFiles.map { it.absolutePath }.toTypedArray(), DummyProgress)

        val importTask = ImportCameras()
        importTask.path = demoFile.absolutePath
        importTask.format = CamerasFormat.CamerasFormatXML
        importTask.apply(chunk, ConsoleProgress(lineSeparator = "\n"))

        // This is the part that fails
        chunk.cameras.forEach { camera ->
            println(camera.label)
        }
    }

    object DummyProgress : Progress {
        override fun progress(progress: Double) {
            println("Progress: $progress")
        }

        override fun status(status: String?) {
            println("Status: $status")
        }

        override fun aborted(): Boolean = false
    }
}

The code is launched with the following environment variables:
Code: [Select]
LD_LIBRARY_PATH=/home/one-tb-drive/git/image-converter/metashape-java-api-2.2.0/jniLibs/linux64:$LD_LIBRARY_PATH

and the JVM is launched with the following VM parameters:
Code: [Select]
-ea -Djava.library.path="/home/one-tb-drive/git/image-converter/metashape-java-api-2.2.0/jniLibs/linux64"

The code fails when it tries to enumerate the cameras (chunk.cameras.forEach { camera -> }) with the following error:

Code: [Select]
/usr/lib/jvm/java-21-openjdk-amd64/bin/java: symbol lookup error: /home/one-tb-drive/git/image-converter/metashape-java-api-2.2.0/jniLibs/linux64/libmetashape.so: undefined symbol: _ZNK8JniUtils15createLongArrayERKSt6vectorIxSaIxEE

What I found out so far:
When unmangling the "undefined symbol", I found that the library fails to resolve JniUtils.createLongArray(). One assumption that I have is that the library is compiled with the JNI headers of Java 1.8 whereas I am using Java 21, which could cause discrepancies in the ABI. Unfortunately, I am heavily relying on newer Java features and am therefore unable to downgrade to Java 8.

My environment:
Code: [Select]
$ java -version
java -version
openjdk version "21.0.6" 2025-01-21
OpenJDK Runtime Environment (build 21.0.6+7-Ubuntu-124.04.1)
OpenJDK 64-Bit Server VM (build 21.0.6+7-Ubuntu-124.04.1, mixed mode, sharing)

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.2 LTS
Release:        24.04
Codename:       noble

I'd like to hear if anyone else has faced this issue and what a potential fix could be. Thanks!

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 15413
    • View Profile
Hello vatbub,

Thank you for reporting the problem

We have implemented the fix JniUtils problem, it will be included to the next version update.
Best regards,
Alexey Pasumansky,
Agisoft LLC