Recent Entries »

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

Java and Soft References

In a previous post, I described what weak references were and how the JVM interacted with them and how they contrasted with strong references. In summary, a strong reference is what we typically think of as a reference in Java; that is, when we instantiate an object and assign its reference to a variable, that is a strong reference. Obviously, these objects will not be cleared by the garbage collector (GC) until the reference is removed.

By contrast, a weak reference doesn’t prevent the garbage collector from clearing the referred object. That is, if the only references that remain to an object are weak references, that object will be treated as if there are no strong references to it, and thus it will be cleared by the GC on its next run. Weak references are implemented mainly by the WeakReference “wrapper” and WeakHashMap, the latter of which only maintains weak references to the keys, so that once the keys are inaccessible (i.e. no strong references exist), the WeakHashMap will automatically drop/remove the corresponding entries, which can also make the value objects eligible for GC so as long as there are no other references to them.

But how do these references contrast with a soft reference?

Continued