diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/CoreStatement.java b/bindings/java/src/main/java/org/github/tursodatabase/core/CoreStatement.java
new file mode 100644
index 000000000..f71827d07
--- /dev/null
+++ b/bindings/java/src/main/java/org/github/tursodatabase/core/CoreStatement.java
@@ -0,0 +1,5 @@
+package org.github.tursodatabase.core;
+
+// TODO: add fields and methods
+public class CoreStatement {
+}
diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/DB.java b/bindings/java/src/main/java/org/github/tursodatabase/core/DB.java
new file mode 100644
index 000000000..4d82a7a92
--- /dev/null
+++ b/bindings/java/src/main/java/org/github/tursodatabase/core/DB.java
@@ -0,0 +1,176 @@
+package org.github.tursodatabase.core;
+
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Interface to Limbo. It provides some helper functions
+ * used by other parts of the driver. The goal of the helper functions here
+ * are not only to provide functionality, but to handle contractual
+ * differences between the JDBC specification and the Limbo API.
+ */
+public abstract class DB {
+ private final String url;
+ private final String fileName;
+ private final AtomicBoolean closed = new AtomicBoolean(true);
+
+ public DB(String url, String fileName) throws SQLException {
+ this.url = url;
+ this.fileName = fileName;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public boolean isClosed() {
+ return closed.get();
+ }
+
+ /**
+ * Aborts any pending operation and returns at its earliest opportunity.
+ */
+ public abstract void interrupt() throws SQLException;
+
+ /**
+ * Executes an SQL statement.
+ *
+ * @param sql SQL statement to be executed.
+ * @param autoCommit Whether to auto-commit the transaction.
+ * @throws SQLException if a database access error occurs.
+ */
+ public final synchronized void exec(String sql, boolean autoCommit) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /**
+ * Creates an SQLite interface to a database for the given connection.
+ * @see SQLite Open Flags
+ *
+ * @param fileName The database.
+ * @param openFlags Flags for opening the database.
+ * @throws SQLException if a database access error occurs.
+ */
+ public final synchronized void open(String fileName, int openFlags) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /**
+ * Closes a database connection and finalizes any remaining statements before the closing
+ * operation.
+ *
+ * @throws SQLException if a database access error occurs.
+ */
+ public final synchronized void close() throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /**
+ * Compiles an SQL statement.
+ *
+ * @param stmt The SQL statement to compile.
+ * @throws SQLException if a database access error occurs.
+ */
+ public final synchronized void prepare(CoreStatement stmt) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /**
+ * Destroys a statement.
+ *
+ * @param safePtr the pointer wrapper to remove from internal structures.
+ * @param ptr the raw pointer to free.
+ * @return Result Codes
+ * @throws SQLException if a database access error occurs.
+ */
+ public synchronized int finalize(SafeStmtPtr safePtr, long ptr) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /**
+ * Creates an SQLite interface to a database with the provided open flags.
+ * @see SQLite Open Flags
+ *
+ * @param filename The database to open.
+ * @param openFlags Flags for opening the database.
+ * @throws SQLException if a database access error occurs.
+ */
+ protected abstract void _open(String filename, int openFlags) throws SQLException;
+
+ /**
+ * Closes the SQLite interface to a database.
+ *
+ * @throws SQLException if a database access error occurs.
+ */
+ protected abstract void _close() throws SQLException;
+
+ /**
+ * Compiles, evaluates, executes and commits an SQL statement.
+ *
+ * @param sql An SQL statement.
+ * @return Result code.
+ * @throws SQLException if a database access error occurs.
+ */
+ public abstract int _exec(String sql) throws SQLException;
+
+ /**
+ * Compiles an SQL statement.
+ *
+ * @param sql An SQL statement.
+ * @return A SafeStmtPtr object.
+ * @throws SQLException if a database access error occurs.
+ */
+ protected abstract SafeStmtPtr prepare(String sql) throws SQLException;
+
+ /**
+ * Destroys a prepared statement.
+ *
+ * @param stmt Pointer to the statement pointer.
+ * @return Result code.
+ * @throws SQLException if a database access error occurs.
+ */
+ protected abstract int finalize(long stmt) throws SQLException;
+
+ /**
+ * Evaluates a statement.
+ *
+ * @param stmt Pointer to the statement.
+ * @return Result code.
+ * @throws SQLException if a database access error occurs.
+ */
+ public abstract int step(long stmt) throws SQLException;
+
+ /**
+ * Executes a statement with the provided parameters.
+ *
+ * @param stmt Stmt object.
+ * @param vals Array of parameter values.
+ * @return True if a row of ResultSet is ready; false otherwise.
+ * @throws SQLException if a database access error occurs.
+ * @see SQLite Exec
+ */
+ public final synchronized boolean execute(CoreStatement stmt, Object[] vals) throws SQLException {
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ /**
+ * Executes an SQL INSERT, UPDATE or DELETE statement with the Stmt object and an array of
+ * parameter values of the SQL statement.
+ *
+ * @param stmt Stmt object.
+ * @param vals Array of parameter values.
+ * @return Number of database rows that were changed or inserted or deleted by the most recently
+ * completed SQL.
+ * @throws SQLException if a database access error occurs.
+ */
+ public final synchronized long executeUpdate(CoreStatement stmt, Object[] vals) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+}
diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java
new file mode 100644
index 000000000..095da6910
--- /dev/null
+++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboDB.java
@@ -0,0 +1,94 @@
+package org.github.tursodatabase.core;
+
+
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+
+/**
+ * This class provides a thin JNI layer over the SQLite3 C API.
+ */
+public final class LimboDB extends DB {
+ /**
+ * SQLite connection handle.
+ */
+ private long pointer = 0;
+
+ private static boolean isLoaded;
+ private static boolean loadSucceeded;
+
+ static {
+ if ("The Android Project".equals(System.getProperty("java.vm.vendor"))) {
+ System.loadLibrary("sqlitejdbc");
+ isLoaded = true;
+ loadSucceeded = true;
+ } else {
+ // continue with non Android execution path
+ isLoaded = false;
+ loadSucceeded = false;
+ }
+ }
+
+ // TODO: receive config as argument
+ public LimboDB(String url, String fileName) throws SQLException {
+ super(url, fileName);
+ }
+
+ /**
+ * Loads the SQLite interface backend.
+ *
+ * @return True if the SQLite JDBC driver is successfully loaded; false otherwise.
+ */
+ public static boolean load() throws Exception {
+ if (isLoaded) return loadSucceeded;
+
+ try {
+ System.loadLibrary("_limbo_java");
+ loadSucceeded = true;
+ } finally {
+ isLoaded = true;
+ }
+ return loadSucceeded;
+ }
+
+ // WRAPPER FUNCTIONS ////////////////////////////////////////////
+
+ @Override
+ protected synchronized void _open(String file, int openFlags) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ // TODO: add support for JNI
+ synchronized native void _open_utf8(byte[] fileUtf8, int openFlags) throws SQLException;
+
+ // TODO: add support for JNI
+ @Override
+ protected synchronized native void _close() throws SQLException;
+
+ @Override
+ public synchronized int _exec(String sql) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ // TODO: add support for JNI
+ synchronized native int _exec_utf8(byte[] sqlUtf8) throws SQLException;
+
+ // TODO: add support for JNI
+ @Override
+ public native void interrupt();
+
+ @Override
+ protected synchronized SafeStmtPtr prepare(String sql) throws SQLException {
+ // TODO: add implementation
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ // TODO: add support for JNI
+ @Override
+ protected synchronized native int finalize(long stmt);
+
+ // TODO: add support for JNI
+ @Override
+ public synchronized native int step(long stmt);
+}
diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/SafeStmtPtr.java b/bindings/java/src/main/java/org/github/tursodatabase/core/SafeStmtPtr.java
new file mode 100644
index 000000000..7c6902c42
--- /dev/null
+++ b/bindings/java/src/main/java/org/github/tursodatabase/core/SafeStmtPtr.java
@@ -0,0 +1,5 @@
+package org.github.tursodatabase.core;
+
+// TODO: add fields and methods
+public class SafeStmtPtr {
+}