Recent Entries »

Sunsetting this blog

I will most likely be sunsetting this blog soon, and moving on to something like a static site generator for any future content. (I’m currently leaning in the direction of Hugo)

I started this blog back in May of 2006 as a place to post my thoughts, and during that time I’ve accumulated quite a lot of content. However, the rate of posts has slowed considerably, to only a handful each year, to the point where I don’t feel it makes sense for me to maintain this WordPress installation anymore.

Additionally, there’s tons of older content that is no longer accurate, and no longer updated. I don’t want to have the burden of keeping that inaccurate information up to date.

I haven’t decided whether I’ll archive all the content from this blog, but if I do, I will likely use something like this WordPress Plugin to export all the existing content. This may result in styles and links being broken, but at least the content would remain available as a record of sorts.

My aim for the new site is just to publish stuff occasionally, and for that, it seems like a static site generator is more than enough. It would also give me the chance to finally redesign this site into something much more simple.

Update: The new site is now live! Please have a visit at peterchng.com.

Getting the Garmin Connect IQ SDK to work with Java 9, 10

If you’re developing with the Connect IQ SDK and have Java 9 or 10 installed (or any version beyond Java 8), you’ll probably run into an issue like this when trying to compile your app with monkeyc or run it with monkeydo, whether from the command line or the Eclipse Plugin:

$ monkeydo myApp.prg fenix5
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
  at com.garmin.monkeybrains.prgreader.EntryPoint.parse(EntryPoint.java:71)
  at com.garmin.monkeybrains.prgreader.EntryPoints.parse(EntryPoints.java:21)
  at com.garmin.monkeybrains.prgreader.PrgParser.parse(PrgParser.java:50)
  at com.garmin.monkeybrains.monkeydodeux.MonkeyDoDeux.execute(MonkeyDoDeux.java:244)
  at com.garmin.monkeybrains.monkeydodeux.MonkeyDoDeux.main(MonkeyDoDeux.java:146)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter
  at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
  at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
  ... 5 more

This is because the monkeybrains.jar that comes with the SDK (and is used by monkeyc and monkeydo) relies on JAXB classes – specifically those from the java.xml.bind package.

Although these are still included in Java 9 and 10, they are not included on the classpath by default, because they were considered to be “Java EE” APIs. One way to get them back on the classpath is to use the --add-modules java.xml.bind command line option when invoking java.

You can fix this by modifying the monkeydo file located in your Connect IQ SDK’s bin directory, i.e. at ./connectiq-sdk-mac-3.0.1/bin/monkeydo: Find the line with the java command, comment it out, and replace with the one below.

# COMMENT THIS ONE OUT:
# Push the executable to the simulator
#java -classpath "$MB_HOME"/monkeybrains.jar com.garmin.monkeybrains.monkeydodeux.MonkeyDoDeux -f "$PRG_PATH" -d $DEVICE_ID -s "$MB_HOME"/shell $TEST_FLAG $TEST_NAME

# USE THIS ONE INSTEAD:
# Fix for Java 9, 10:
# https://stackoverflow.com/questions/43574426/how-to-resolve-java-lang-noclassdeffounderror-javax-xml-bind-jaxbexception-in-j
java --add-modules java.xml.bind -classpath "$MB_HOME"/monkeybrains.jar com.garmin.monkeybrains.monkeydodeux.MonkeyDoDeux -f "$PRG_PATH" -d $DEVICE_ID -s "$MB_HOME"/shell $TEST_FLAG $TEST_NAME

After this, monkeydo should work correctly in running your compiled app in the simulator. (Note: I did not have to make changes to the monkeyc command)

Java PhantomReferences: A better choice than finalize()

We’ve talked about soft and weak references, and how they differ from strong references. But what about phantom references? What are they useful for?

Starting with Java 9, the intended usage of PhantomReference objects is to replace any usage of Object.finalize() (which was deprecated in Java 9), in order to allow for this sort of object clean-up code to be run in a more predicable manner (as designated by the programmer), rather than subject to the constraints/implementation details of the garbage collector.

Continued