HDFView does not register the HDF4 file format at startup, and consequently HDF4 files are not recognized and cannot be opened.
With debug logging enabled the HDF4 format registration failure can be seen:
DEBUG FileFormat - FILE_TYPE_HDF4 instance failure:
java.lang.NullPointerException: Cannot invoke "org.slf4j.Logger.trace(String, Object[])"
because "hdf.object.h4.H4File.log" is null
at hdf.object.h4.H4File.<init>(H4File.java:162)
at hdf.object.h4.H4File.<init>(H4File.java:96)
at hdf.object.FileFormat.<clinit>(FileFormat.java:202)
at hdf.view.ViewProperties.load(ViewProperties.java:1502)
at hdf.view.HDFView.<init>(HDFView.java:267)
The cause is that ViewProperties.load() walks the module.fileformat.* preferences and calls Class.forName on each value (ViewProperties.java:1502). For HDF4 that is hdf.object.h4.H4File, and it is the first touch of either class. Because H4File extends FileFormat (H4File.java:46), the JVM has to initialize FileFormat first, which runs FileFormat's static block. That block calls Class.forName("hdf.object.h4.H4File") and newInstance() (FileFormat.java:201-202). H4File's initialization is already in progress on this same thread, so the JVM returns immediately instead of waiting for it to finish.
The result is that H4File's constructor runs while H4File's own static initialization is still parked at the superclass step. Its private static final Logger log (H4File.java:49) has not been assigned yet, so the log.trace call at H4File.java:162 throws an NPE.
Only HDF4 is affected, since H5File's constructor never touches the log. The initialization cycle applies to any format class that gets loaded first, but H4File is the only one that dereferences its logger before initialization has completed.
The cheapest fix is to remove the log.trace at H4File.java:162, or guard it. That would get HDF4 working, but the issue will crop back up the next time a log statement is added.
A longer term fix is to stop FileFormat's static initializer from instantiating its own subclasses. Registering formats lazily, or moving registration to an explicit init call, would suffice.
HDFView does not register the HDF4 file format at startup, and consequently HDF4 files are not recognized and cannot be opened.
With debug logging enabled the HDF4 format registration failure can be seen:
The cause is that ViewProperties.load() walks the module.fileformat.* preferences and calls Class.forName on each value (ViewProperties.java:1502). For HDF4 that is hdf.object.h4.H4File, and it is the first touch of either class. Because H4File extends FileFormat (H4File.java:46), the JVM has to initialize FileFormat first, which runs FileFormat's static block. That block calls Class.forName("hdf.object.h4.H4File") and newInstance() (FileFormat.java:201-202). H4File's initialization is already in progress on this same thread, so the JVM returns immediately instead of waiting for it to finish.
The result is that H4File's constructor runs while H4File's own static initialization is still parked at the superclass step. Its private static final Logger log (H4File.java:49) has not been assigned yet, so the log.trace call at H4File.java:162 throws an NPE.
Only HDF4 is affected, since H5File's constructor never touches the log. The initialization cycle applies to any format class that gets loaded first, but H4File is the only one that dereferences its logger before initialization has completed.
The cheapest fix is to remove the log.trace at H4File.java:162, or guard it. That would get HDF4 working, but the issue will crop back up the next time a log statement is added.
A longer term fix is to stop FileFormat's static initializer from instantiating its own subclasses. Registering formats lazily, or moving registration to an explicit init call, would suffice.