J2ME in 2026
Basically all tutorials on J2ME I can find are
- ancient
- assuming you're using some kind of IDE
- working off of Sun's WTK
- some combination of the above
I have, fortunately however, managed to piece together enough information to be able to do so. I'll walk through building a simple J2ME app, using only free software that's still maintained (well, mostly) so that this is documented somewhere.
For tooling, we'll be using
- OpenJDK 8
- Still maintained for the time being. It's the last version of OpenJDK that supports code generation for the old versions of Java we're targeting.[citation needed]
- ProGuard
- We're not interested in "protecting" our application, but J2ME requires preverification and ProGuard appears to be the best choice here somehow.
- MicroEmulator
- Okay this one's not actually maintained anymore. But we're just using their stub libraries for the J2ME APIs.
- bsdtar
- Other ZIP-file creation utilities are available.
- FFmpeg
- Other image processing utilities are available.
$ mkdir -p ro/plesoianu lib out/ro/plesoianu out/META-INF
$ cd ro/plesoianu
ro/plesoianu$ wcurl https://felix.plesoianu.ro/mobile/pocket-gopher/PocketGopher.java
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 22743 100 22743 0 0 28807 0 0
ro/plesoianu$ cd ../../lib
lib$ wcurl https://repo1.maven.org/maven2/org/microemu/midpapi20/2.0.4/midpapi20-2.0.4.jar https://repo1.maven.org/maven2/org/microemu/cldcapi11/2.0.4/cldcapi11-2.0.4.jar
DL% UL% Dled Uled Xfers Live Total Current Left Speed
100 -- 87390 0 2 0 449k
lib$ cd ..
$ /usr/local/openjdk8/bin/javac -source 1.2 -target 1.2 -d out -bootclasspath lib/midpapi20-2.0.4.jar:lib/cldcapi11-2.0.4.jar ro/plesoianu/PocketGopher.java
warning: [options] source value 1.2 is obsolete and will be removed in a future release
warning: [options] target value 1.2 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
3 warnings
$ cd out
out$ wcurl https://felix.plesoianu.ro/mobile/pocket-gopher/home.txt
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1245 100 1245 0 0 3383 0 0
out$ ffmpeg -loglevel error -f pbm_pipe -i - gdimp.png << EOT
> P1
> 32 32
> 0000000000000000000000000000000000000000000000000000000000000000000000
> 0000000000000000000000000000000000000000000000000000000000000001110000
> 0000000000000000000000001100000000000000000000000000000110000000000000
> 0000000010000000010000000000011000000001100000000100000000001010011000
> 0100000000110010000001101001111001110000001001111000110010010010011100
> 0000110001100010001001001001011000000111110000111010010110010010000000
> 0000000000111011110000001000000000000000000000111000000010000000000000
> 0000000011000000001000000000000000000000100000000000000000000000000000
> 0000000000000000000000111100000000000000000000000000001001111100000000
> 0000000000000000100000010000000000000000000000001000001100011110000000
> 0000000000111011100001101100000000000000000011100000011001100000000000
> 0000000011000001100000000000000000000000010000010000000000000000000000
> 0000000001000000000000000000000000000000010000000000000000000000000000
> 0001000000000000000000000000000000000000000000000000000000000000000000
> 00000000000000000000000000000000000000000000
> EOT
out$ unix2dos > META-INF/MANIFEST.MF << EOT
> Manifest-Version: 1.0
> MicroEdition-Configuration: CLDC-1.1
> MicroEdition-Profile: MIDP-2.0
> MIDlet-1: Pocket Gopher rebuilt, /gdimp.png, ro.plesoianu.PocketGopher
> MIDlet-Description: Rebuild of PocketGopher sources in 2026
> MIDlet-Icon: /gdimp.png
> MIDlet-Info-URL: http://microblog.ahti.space/nortti/2026-08-25-j2me-in-2026.html
> MIDlet-Name: Pocket Gopher rebuilt
> MIDlet-Vendor: Felix Pleșoianu, nortti
> MIDlet-Version: 1.0
> EOT
out$ tar -cf ../not-preverified.jar --format zip *
out$ cd ..
$ proguard -injars not-preverified.jar -outjars pocketgopher-rebuilt.jar -libraryjars lib/midpapi20-2.0.4.jar -libraryjars lib/cldcapi11-2.0.4.jar -dontshrink -dontoptimize -dontobfuscate -microedition
ProGuard, version 7.0.0
Reading program jar [not-preverified.jar] (filtered)
Reading library jar [lib/midpapi20-2.0.4.jar] (filtered)
Reading library jar [lib/cldcapi11-2.0.4.jar] (filtered)
Preparing output jar [pocketgopher-rebuilt.jar] (filtered)
Copying resources from program jar [not-preverified.jar] (filtered)
Inshallah I'll write a proper writeup that exaplains what every bit here actually is for. For now, my sources were:
- Creating deployable MIDlets with free software,
- Pointed me at the proper FOSS software to look at and explained what ProGuard is actually needed for.
- [EN] (Much) Faster Way to J2ME Development in 2026, 2026
- Told me where to get the MicroEmulator stub libraries nowadays (the answer is Maven Central).
- sdk/compile.sh in the discord-j2me project
- Showed the actual commands to run if you are not using an IDE.