I’ve got a legacy windows app that I need to run from time to time. The app is written in java, but uses some 32 bit JNI dlls. I’ve used to keep a windows VM around just to run it, but recently I was able to “port” it to wine.
In short, you can need install wine on ubuntu:
# I've needed a 32 bit version $ sudo dpkg --add-architecture i386 $ sudo apt-get -y update && sudo apt-get install wine32
Then get the 32bit JDK from Oracle. It needs to be JDK, JRE wasn’t working for me (and some folks on the internet). As of time of writing I’ve got JDK 8u192 and this is what I’ve tested with.
$ chmod +x ~/Downloads/jre-8u192-windows-i586.exe $ wine ~/Downloads/jre-8u192-windows-i586.exe
This starts a graphical installer, though later on, I’ve found out there is a
/s for silent mode.
Then you can rock your legacy 32bit JNI app, no issues:
# Windows path to java: export JAVA_EXE='C:\Program Files (x86**\Java\jdk1.8.0_192\bin\java.exe' # JNI library path, can be relative to the working directory export JNI=lib/win32 wine "$JAVA_EXE" -cp "legacy-app.jar" -Djna.library.path="$JNI" "com.legacy.MainClass"
I’m really impressed that wine can run a windows JVM. Next step would be to dockerize the whole thing and forget it was ever a pain to run :)
Update (few hours later):
I couldn’t help it and dockerize this. The benefits are that I don’t need to install wine and then JVM on my machine, I get it to run on a server somewhere in the cloud in time, but most importantly, I’ve got a documented and reproducible sequence of steps. And I can share them with my readers :)
Nothing fancy here, we’ve jsut scripted the steps outlined earlier. Some
improvements can be done if you care about the image size (e.g.
ubuntu is not the
smallest base, no need to keep
jdk.exe after the installation, etc.).
Note that I install the jvm with
/s so this can be done headless, that is
without the X server, as there is no graphical output or buttons to click.
Before build the image, please download the JVM installer from Oracle and put it
in the same directory as the
build — builds the image with a preconfigured label.
We cloud push the image to a dockerhub, but this is a personal project for me,
so I don’t want to invest in a private repo, and I’m not sure if this is
all-right with Oracle if I share their precious JVM with the world publicly. For
that reason we have also
load-image to easily migrate to
another machine (or stash somewhere safe to prepare for an SSD
Again, these are just the instructions pasted above, wrapped in a container. We
docker run, then
--rm to discard the container afterwards.
-w to mount the current working directory in the container. Then we just pass
Also note, that my legacy app reads from disk and writes to disk. It can run in a batch mode without GUI. If you need a GUI in your app, the easiest thing to do seems to be to mount the X socket and reuse the session. For details check this blogpost.
Hope this is helpfully. I’m really happy that I was able to get rid of the manual steps (and the pain of maintaining Windows VM) and turned it into scripted, isolated and linux-friendly procedure.