Skip to content

Archives

DynamoDB-local on Apple Silicon

DynamoDB Local is one of the best features of AWS DynamoDB. It allows you to run a local instance of the data store, and is perfect for use in unit tests to validate correctness of your DynamoDB client code without calling out to the real service “in the cloud” and involving all sorts of authentication trickiness.

Unfortunately, if you’re using one of the new MacBooks with M1 Apple silicon, you may run into trouble:

11:08:56.893 [DEBUG] [TestEventLogger]          DynamoDB > Feb 04, 2022 11:08:56 AM com.almworks.sqlite4java.Internal log
11:08:56.893 [DEBUG] [TestEventLogger]          DynamoDB > SEVERE: [sqlite] SQLiteQueue[]: error running job queue
11:08:56.893 [DEBUG] [TestEventLogger]          DynamoDB > com.almworks.sqlite4java.SQLiteException: [-91] cannot load library: java.lang.UnsatisfiedLinkError: /.../DynamoDBLocal_lib/libsqlite4java-osx.dylib: dlopen(/.../DynamoDBLocal_lib/libsqlite4java-osx.dylib, 0x0001): tried: '/.../DynamoDBLocal_lib/libsqlite4java-osx.dylib' (fat file, but missing compatible architecture (have 'i386,x86_64', need 'arm64e')), '/usr/lib/libsqlite4java-osx.dylib' (no such file)
11:08:56.893 [DEBUG] [TestEventLogger]          DynamoDB >      at com.almworks.sqlite4java.SQLite.loadLibrary(SQLite.java:97)
11:08:56.893 [DEBUG] [TestEventLogger]          DynamoDB >      at com.almworks.sqlite4java.SQLiteConnection.open0(SQLiteConnection.java:1441)
11:08:56.893 [DEBUG] [TestEventLogger]          DynamoDB >      at com.almworks.sqlite4java.SQLiteConnection.open(SQLiteConnection.java:282)
11:08:56.894 [DEBUG] [TestEventLogger]          DynamoDB >      at com.almworks.sqlite4java.SQLiteConnection.open(SQLiteConnection.java:293)

It’s possible to invoke it via Rosetta, Apple’s qemu-based x86 emulation layer, like so:

arch -x86_64 /path/to/openjdk/bin/java dynamodb-local.jar

But if you don’t have control over the invocation of the Java command, or just don’t want to involve emulation, this is a bit hacky. Here’s a better way to make it work.

First, download dynamodb_local_latest.tar.gz from the DynamoDB downloads page, and extract it.

The DynamoDBLocal_lib/libsqlite4java-osx.dylib file in this tarball is the problem. It’s OSX x86 only, and will not run with an ARM64 JVM. However, the same lib is available for ARM64 in the libsqlite4java artifacts list, so this will work:

wget -O libsqlite4java-osx.dylib.arm64 'https://search.maven.org/remotecontent?filepath=io/github/ganadist/sqlite4java/libsqlite4java-osx-arm64/1.0.392/libsqlite4java-osx-arm64-1.0.392.dylib'
mv DynamoDBLocal_lib/libsqlite4java-osx.dylib libsqlite4java-osx.dylib.x86_64
lipo -create -output libsqlite4java-osx.dylib.fat libsqlite4java-osx.dylib.x86_64 libsqlite4java-osx.dylib.arm64
mv libsqlite4java-osx.dylib.fat DynamoDBLocal_lib/libsqlite4java-osx.dylib

This is now a “fat” lib which supports both ARM64 and x86 hardware. Hey presto, you can now invoke DynamoDBLocal in the normal Rosetta-free manner, and it’ll all work — on both hardware platforms.

(This post is correct as of version 2022-1-10 (1.18.0) of DynamoDB-Local — let me know by mail, or at @jmason on Twitter, if things break in future, and I’ll update it.)