Saturday, January 19, 2019

How to create a .jar association for your OpenJDK

From Java 11, Oracle has changed the license of their JDK, so you probably may want (or even have) to move to OpenJDK, and if you have moved already to OpenJDK, you may have noticed that clicking on a .jar didn't work anymore as it did with Oracle JDK binaries. This is because most of the pre-build OpenJDK binaries are coming without an installer on Microsoft Windows. Fortunately, it is easy to fix - with jarfix.

In the following example I show you how to use jarfix in order to setup the .jar association for your OpenJDK.

1. Download the OpenJDK

Download the OpenJDK from the source of your choice. You could get it from or for example. Actually there are many more sources where you can get it, but I have downloaded the latest OpenJDK from, and extracted the .zip file to C:\Applications\jdk-11.0.1+13

2. Download jarfix

Download jarfix.exe from the jarfix homepage and store the .exe on a folder of your choice on your harddrive. On my Windows instance, I have stored the jarfix.exe to C:\Applications\jarfix\

3. Create a jarfix config file

Create a jarfix.ini file to C:\Applications\jarfix\ with the following content:

action="C:\Applications\jdk-11.0.1+13\bin\javaw.exe" -jar  "%1" %*

Those entries tell jarfix to setup a .jar association with the OpenJDK in C:\Applications\jdk-11.0.1+13\ - you may want to modify that path according to the actual path that you have choosen at step 1. The line called "options=/a" is optional, it tells jarfix to create a "Open as Administrator" menu entry in order to run .jar files also under the Admin account.

Hint: you can run jarfix /x in order to extract an example jarfix.ini file which has a lot of useful examples for a Java developer on Windows.

Update January 27, 2019: from Jarfix version 3 you can recreate hijacked .jar associations out of the box (by a double click without an .ini file) not only for the Oracle JDK, but also for the OpenJDK from Azul Systems.

4. Run jarfix using the config file

Open a Windows Command Prompt or simply hit both the Windows Key and R in order to enter the following command:

C:\Applications\jarfix\jarfix.exe /c

Update January 27, 2019: from Jarfix version 3 it is not necessary anymore to pass the option /c as a parameter. If a .ini file exists with the same name as the .exe in the same directory, jarfix will read the .ini file in order to initialize itself with the values from the .ini. In other words, you can simply double click on jarfix.exe and the content of jarfix.ini will be taken into account.

5. Test it

If you have run "jarfix /x" at step 3, you can double click on the existing jartest.jar in C:\Applications\jarfix in order to test whether it works as expected:

As you can see above we have launched the OpenJDK from AdoptOpenJDK by double-clicking on a .jar file.

Thursday, July 12, 2018

How to install or update your preferred JDK with one single command on macOS or GNU/Linux?

What is your preferred JRE/JDK? Is it the Oracle JDK from or the JRE from, the OpenJDK from or the OpenJDK from or Whatever your preference is, you can install or update the JDK with only one single command on macOS or GNU/Linux with the bash script called update_jdk.

You can download it from here for free:

And here comes the one-liner:

sudo ./update_jdk -az -s -t openjdk10 /opt/java/jdk/
The command above downloads the OpenJDK 10 from (you can specify the source and type with -s and -t), extracts it, applies the latest time zone data from IANA by downloading, extracting and calling the latest time zone updater (you have to accept the Oracle license by specifying the -a option) and it saves .version files that store the URI of the actual download for re-run purposes (see below). In /opt/java/jdk/ you will then find symlinks that point to the latest latest updated OpenJDK 10 folder (and the latest tzupdater.jar if you run the script with -z). Now you have a fixed path that you can use to configure your IDE, apps, whatever.
$ /opt/java/jdk/openjdk10_latest/bin/java -version
openjdk version "10.0.1-adoptopenjdk" 2018-04-17
OpenJDK Runtime Environment (build 10.0.1-adoptopenjdk+10)
OpenJDK 64-Bit Server VM (build 10.0.1-adoptopenjdk+10, mixed mode)
If you re-run the script above, it will only download the bits if they are different from those that you have downloaded already (it simply compares the .version file), updates the JDK that you have specified with -t and recreates the symlinks. So with the update_jdk script you stay up to date the easy way.

Update Aug 24, 2018:
bash-dwarfs has been renamed to bashberries

Update Sep 23, 2018:
update_jre has been renamed to update_jdk

Sunday, June 17, 2018

NumericalChameleon is running in the web browser using Webswing

Today I run the NumericalChameleon (a Swing based app) in my web browser on my desktop by using Webswing. It really works like a charm! The NC GUI acts in just the same way as it does when running natively.

It works like a charm - in the web browser on the desktop

I downloaded and installed Webswing 2.5.4. and I did no modifications on the NumericalChameleon 2.1.0. I just copied the NC folder to the Webswing demo folder and entered some values at the configuration dialog such as Name, Icon, Home Folder, Working Directory, Class Path, etc. After I have configured it in Webswing, the app appears in the app list of Webswing:

The NC GUI acts in just the same way as it does when running natively on bare metal.

Even theme selection, language selection, restarting the app, updating exchange rates and audio was working (at least when the process is running on localhost)! The performance is surprisingly good, although a little bit slower if I compare it with native performance.

One (minor) problem I found was that opening help and opening data tables didn't work, because the help files and data tables are stored locally as HTML. In the log I found traces of "WebPaintDispatcher:notifyOpenLinkAction", so the action was recognized, but no action happened.

Normal http links were working, however.

It didn't work well on the smart phone, though

I also tried to access the above setup on my smart phone, but without having a screen keyboard, the usage of a Swing app in the browser is very limited, especially if I rely on entering numbers to a software. Also it seems not to be possible to move windows around inside the browser. At least it was pretty funny to hear the numbers spoken by NC on my desktop audio boxes when I pushed the play sound button on my smartphone ;-)


In the web browser on the desktop using Webswing, the Swing based app NumericalChameleon is working pretty well actually. It is worth to try it!

Sunday, March 11, 2018

... and all I got was this lousy T-shirt

To be honest, it is not a lousy T-shirt at all, it is great T-shirt from the Linux Foundation actually. It has a simplified Tux icon and a little riddle on its front:

Warning: don't scroll down if you want to solve the riddle by your own. Scroll down in order to see how I solved the riddle.
   2nd WARNING
   Ok, either you have solved the riddly by your own or you are simply too curious ;-)
Actually, I was wondering whether I can solve the riddle by using the NumericalChameleon (yeah, you know I am the author of it, don't you?) and I am glad to announce that it can be used to solve the riddle as well. I entered the bitstream at the category "Positional Notations, Radix 2-36", and converted the value to hex. Since the Unicode character set is a superset of ASCII, and numbers 0 - 127 have the same meaning in ASCII as they have in the Unicode character set, it was possible to prefix each hex number by 00 in order to satisfy the expected input format at the "Unicode® Characters (Basic Multilingual Plane)" category. Below you see screenshots of both the NumericalChameleon (with the solution) and a hex editor in the background (with the solution) in order to verify the result.

Sunday, October 22, 2017

How to open your browser from bash on Windows (WSL), GNU/Linux, macOS and Solaris

Sometimes it can be useful to open a browser from your bash. I have developed a bash function that does exactly that - and since I am a fan of multiple operating systems - the function works not only on GNU/Linux, macOS, and Solaris but also on the bash on Windows as part of the WSL (Windows Subsystem for Linux).

function openBrowser() {
  OS=$(uname -s)
  case "$OS" in
          open "$URL"
          if [[ "$(cat /proc/sys/kernel/osrelease)" =~ "Microsoft" ]]; then
              # We are in bash on WSL (Windows Subsystem for Linux)
              # We don't need a Linux-Browser and an X-Server,
              # we just can call iexplore.exe,
              # see also
              if [[ "(uname -p)" == "x86_64" ]]; then
                  /mnt/c/Program\ Files/Internet\ Explorer/iexplore.exe "$URL" 2> /dev/null
                  /mnt/c/Program\ Files\ \(x86\)/Internet\ Explorer/iexplore.exe "$URL" 2> /dev/null
              xdg-open "$URL"
          /usr/dt/bin/sdtwebclient "$URL"
          printf "Not supported on %s\n" "$OS"

To use the function in your bash-script, simply source the file that contains the function - I called the file network.include. You find the file as well at the repository of my tiny project called bashberries - that is a tiny collection of both bash scripts and bash includes, released under the terms of the Apache 2.0 license. The script below calls the function from above and opens the homepage to bashberries:

#!/usr/bin/env bash
. ./network.include

Best regards,

Update Oct 23, 2017:
uname -r is not reliable enough, it does not work on the wls beta with Ubuntu 14.04 for example, better is to do a cat /proc/sys/kernel/osrelease

Update Oct 23, 2017:
bash-dwarfs has been renamed to bashberries.

Friday, June 9, 2017

macOS: To use the java command-line tool you need to install a JDK - are you kidding me?

Recently I detected an error message on macOS saying that it seems to be required to install a JDK in order to just use the java command-line tool. A JRE is not enough? Really? Are you kidding me?

The screenshot below shows the error message in German: "Um das java-Befehlszeilenprogramm nutzen zu können, musst du ein Java-Entwicklerpaket installieren." In English it means: "To use the java command-line tool you need to install a JDK".

Since I am a developer, I always installed the JDK on my Mac and I detected that phenomenon very late. Actually the web is full of those traces - however, without a suitable solution in my opinion. Well, I simply don't want to tell my users to install a JDK if a simple JRE is enough. Any existing JRE on the system should do the job in my humble opinion.

Here we go, here is my little bash launcher that tries its best to launch java even if you have installed a JRE only on your Mac:
if [[ ! -z $JAVA_HOME ]]; then
    LIBEXEC=$(/usr/libexec/java_home 2> /dev/null | head -1)
    # is there a JDK?
    if [[ ! -z $LIBEXEC ]]; then
       # is there a JRE?
       JRE=/Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java
       if [[ -f "$JRE" ]]; then
"$JEXEC" "$@"

The script checks for the JAVA_HOME environment variable and if that is not set, it checks for any registered JDKs by calling /usr/libexec/java_home and if that didn't return anything, it simply uses the JRE that could be available at a well known path on macOS (tested with both Java 8u131 and Java 9-ea) and if that fails as well, it uses java and if even that fails it means you really don't have any Java installed and you should get the error message above again.

I use the launcher above already as part of the Jacksum macOS Finder integration. See also

Feel free to use the launcher script for your Java app as well if it meets your needs.

Sunday, May 28, 2017

Solaris' pargs, penv, pfiles, pmap, pstack, and pwdx on macOS

Three weeks ago I posted Solaris' pargs, penv, pfiles, pmap, and pstack on GNU/Linux and since I am also a Mac user, I thought it could be a good idea to have those commands also on macOS. Here we go ...

function pargs()  { L=$(ps ww $1 | tail -1); echo ${L:27}; }
function penv()   { L=$(pargs $1); C=${#L}; L=$(ps wwe $1 | tail -1); L=${L:27}; echo ${L:$C} | tr ' ' '\n'; }
function pfiles() { lsof -p $1; }
function pmap()   { vmmap $1; }
function pstack() { echo "thread backtrace all" | lldb -p $1; }
function pwdx()   { L=$(lsof -a  -d cwd -p $1 | tail -1); echo /${L#*/}; }

Since there is no access to a proc file system on macOS (at least not by default), both pargs and penv call the ps command and pmap calls vmmap. Furthermore pwdx calls lsof with the current working directory descriptor request in order to get the required info. Since "ps wwe" returns not only the environment variables for the given process but also the program arguments on macOS, we need to strip the program arguments from the output. This has been done by calling pargs, determining the length of that output and cutting that length from the string again before we pass it to the tr command that gives us an environment variable for each line. For blog purposes I have shortened the variable names, L stands for line and C for count.


Sunday, May 7, 2017

Solaris' pargs, penv, pfiles, pmap, and pstack on GNU/Linux

I really like the p-commands on Sun/Oracle Solaris and I miss those on GNU/Linux. Therefore I have gathered/created rudimental equivalent one-liners that work on a PID.

I have added the following functions to my ~/.bash_aliases file that is being sourced by my ~/.bashrc. pargs, penv, and pmap are gathering the proc file system, while pfiles and pstack are calling lsof resp. gdb.

function pargs() { cat /proc/$1/cmdline | tr '\0' ' ' | sed 's/ $/\n/g'; }
function penv() { cat /proc/$1/environ | tr '\0' '\n'; }
function pfiles() { lsof -p $1; }

function pmap() { cat /proc/$1/maps; }
function pstack() { sudo gdb --pid=$1 --batch -ex "thread apply all bt"; }

Note that due to a kernel hardening (ptrace protection) on Ubuntu 10.10 and later you need to call gdb under the control of sudo, or alternatively modify the ptrace_scope property. See also and

Friday, February 10, 2017

How the NumericalChameleon Installer obtains the latest JRE for Windows

Today I will explain how the NumericalChameleon installer obtains the latest Java Runtime Environment (JRE) for Microsoft Windows.

The NumericalChameleon ( is written in Java and it relies on a JRE that is installed on your system. The NumericalChameleon installer checks at first whether a JRE is installed. If there is one, everything is fine and the installer will continue with a normal installation. If there is none, the installer downloads the latest JRE offline installer from Oracle and launches it. The offline installer installs the JRE on your system and once it is installed, it will give back the control to the NumericalChameleon installer that continues with the installation until the NumericalChameleon software package is installed as well.

Below you find a screenshot of the NumericalChameleon installer, localized in German, running on Windows 10 x64 while downloading the latest JRE offline installer:

Since the actual locations of the JRE offline exe installers are different for each Java version, and those locations are both unpredictable and volatile, it is important for the NumericalChameleon installer to rely on well known static URIs, because the installer binary cannot be changed/patched anymore once it is deployed on the web.

Those well known URIs are redirects in the .htaccess file on my Apache server actually, and the redirects are being updated every day. I create those redirects by parsing the website that has the locations of the Windows JRE offline installers.

$ cat bin/update_htaccess


# the locations of the JRE offline installers
CONTENT=$(curl -s "$URL")

IDENTIFIER="Windows Offline</a>"
if [[ "$CONTENT" =~ BundleId=([^\"]+)\"\>[[:space:]]*"$IDENTIFIER" ]]; then
    printf "Redirect /get_java_win32bit\n" ${BASH_REMATCH[1]} >> $HTACCESS

IDENTIFIER="Windows Offline (64-bit)</a>"
if [[ "$CONTENT" =~ BundleId=([^\"]+)\"\>[[:space:]]*"$IDENTIFIER" ]]; then
    printf "Redirect /get_java_win64bit\n" ${BASH_REMATCH[1]} >> $HTACCESS

The .htaccess.static file just contains entries that never change. The update_htaccess script runs by cron periodically on the server in order to have entries that are up to date.

$ crontab -l | tail -1

9 3 * * * cd bin; ./update_htaccess

After the cron was running, updated redirects can be found in the .htaccess file. In the example below the redirects are from Java 8u121:

$ tail -2 .htaccess

Redirect /get_java_win32bit
Redirect /get_java_win64bit

The installer can now rely on the fixed addresses below, dependent whether a 32 bit or a 64 bit system has been found:
Now you know how the NumericalChameleon installer gets the latest JRE on Windows.

Hint: if the approach above should ever fail and the redirects are not being created, the current installer will fail with a 404. In that case you can simply install the JRE manually before you start the NumericalChameleon installer. In that case the installer won't even go to the internet, because the condition is met already that a JRE has to be installed.

Monday, June 6, 2016

The NumericalChameleon 2.0.0 is on the web

I am pleased to announce that the NumericalChameleon 2.0.0 is on the web:

The NumericalChameleon is free, open source, cross platform and comprehensive software in order to convert units with a precision of up to 1000 decimal places. It supports more than 5200 units in 93 categories, including not only all important physical units, but also useful units in non-standard categories like exchange rates, time zones, spoken numbers (literally and by audio), roman numerals, geographic coordinates, radixes, fractions, checksums, bits&bytes, screen resolutions, colorcodes, unicodes, international dial codes, calendar and holiday calculations and many more.

Release notes for the version 2.0.0 are at

Kind Regards,