Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UnsatisfiedLinkError with SQLite JDBC Driver Using System libsqlite3.so on Linux and other OSs #1179

Closed
blakemcbride opened this issue Sep 19, 2024 · 3 comments
Labels
question Further information is requested

Comments

@blakemcbride
Copy link

blakemcbride commented Sep 19, 2024

Describe the bug

When using the SQLite JDBC driver with the system-installed libsqlite3.so on both Linux and OpenIndiana platforms (and presumably others), the Java application fails with an UnsatisfiedLinkError. The driver cannot find the required JNI method implementations in the system's SQLite library.

To Reproduce

  1. Install the SQLite JDBC driver (e.g., sqlite-jdbc-3.46.1.0.jar).

  2. Ensure that the system's libsqlite3.so is present in /usr/lib64.

  3. Run the Java application with the following JVM options:

java \
-Dorg.sqlite.lib.path=/usr/lib64 \
-Dorg.sqlite.lib.name=libsqlite3.so \
-cp .:sqlite-jdbc-3.46.1.0.jar YourMainClass
  1. Use the following sample code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class YourMainClass {
    public static void main(String[] args) {
        String url = "jdbc:sqlite:test.db";
        try (Connection conn = DriverManager.getConnection(url)) {
            if (conn != null) {
                System.out.println("Connection established.");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Expected behavior

The application should successfully establish a connection to the SQLite database using the system-installed libsqlite3.so without any errors.

Logs

Exception in thread "main" java.lang.UnsatisfiedLinkError: 'void org.sqlite.core.NativeDB._open_utf8(byte[], int)'
    at org.sqlite.core.NativeDB._open_utf8(Native Method)
    at org.sqlite.core.NativeDB.open(NativeDB.java:122)
    at org.sqlite.core.DB.open(DB.java:169)
    at org.sqlite.SQLiteConnection.open(SQLiteConnection.java:247)
    at org.sqlite.SQLiteConnection.<init>(SQLiteConnection.java:228)
    at org.sqlite.JDBC.createConnection(JDBC.java:124)
    at org.sqlite.JDBC.connect(JDBC.java:99)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:208)
    at YourMainClass.main(YourMainClass.java:8)

Environment (please complete the following information):

  • OS: Fedora Linux 40, OpenIndiana 2404.04
  • CPU architecture: x86_64
  • sqlite-jdbc version 3.46.1.0

Additional context

  • The system libsqlite3.so lacks the JNI bindings required by the SQLite JDBC driver.

  • This issue occurs when attempting to use the system-installed SQLite library instead of the native library bundled within the driver JAR.

  • The problem is consistent across both Linux and OpenIndiana platforms.

  • Is there a way to configure the driver to work with the system libsqlite3.so without rebuilding the driver or creating custom JNI libraries?

  • Allowing the driver to use the system's SQLite library would enhance compatibility and simplify deployment.

@gotson
Copy link
Collaborator

gotson commented Sep 20, 2024

that can't work, because of this:

  • The system libsqlite3.so lacks the JNI bindings required by the SQLite JDBC driver.

This is how JNI works, you need a specifically compiled library containing the JNI code.

You can check how to compile against your own version of sqlite here:

test_external_amalgamation:
name: test external amalgamation
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 20
java-package: jdk
cache: 'maven'
- run: brew install sqlite3
- name: Find SQLite directory
run: |
BREW_SQLITE_PREFIX=`brew --prefix sqlite3`
echo "SQLITE_DIR=$(dirname ${BREW_SQLITE_PREFIX})/$(readlink ${BREW_SQLITE_PREFIX})" | tee -a $GITHUB_ENV
- name: Make native lib
run: |
make native SQLITE_OBJ=${{ env.SQLITE_DIR }}/lib/libsqlite3.dylib SQLITE_HEADER=${{ env.SQLITE_DIR }}/include/sqlite3.h
- name: Test
run: mvn --batch-mode --no-transfer-progress test

@gotson gotson closed this as not planned Won't fix, can't repro, duplicate, stale Sep 20, 2024
@gotson gotson added question Further information is requested and removed triage labels Sep 20, 2024
@blakemcbride
Copy link
Author

Then, what is the purpose of:
-Dorg.sqlite.lib.path=/usr/lib64 -Dorg.sqlite.lib.name=libsqlite3.so

@gotson
Copy link
Collaborator

gotson commented Sep 23, 2024

Then, what is the purpose of: -Dorg.sqlite.lib.path=/usr/lib64 -Dorg.sqlite.lib.name=libsqlite3.so

to use the binaries you have compiled yourself, for example for architectures that we don't ship in the jar, or if you build against your own amalgamation (as in the workflow i linked above). Or to use a specific version of SQLite that you could have extracted from a previous version of the sqlite-jdbc jar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants