imagej / imagej-launcher

The ImageJ native launcher
https://imagej.net/learn/launcher
BSD 2-Clause "Simplified" License
21 stars 23 forks source link

Update paths for Java 9 #52

Closed stelfrich closed 6 years ago

stelfrich commented 6 years ago

Since Oracle has decided to get rid of 32-bit builds for most OSs, they have removed OS-dependent folders in JRE/JDK folder structures. To keep compatibility, move guess_java_version() to java.c and get rid of circular usage when trying to identify JRE/JDKs.

Closes #51.

ctrueden commented 6 years ago

Thanks a lot for working on this. I have a couple of questions/concerns/ideas here:

  1. Have you tested with Java 10 early access builds a.k.a. Java 18.3? Here is what today's snapshot says:
    $ java -version
    openjdk version "10" 2018-03-20
    OpenJDK Runtime Environment 18.3 (build 10+44)
    OpenJDK 64-Bit Server VM 18.3 (build 10+44, mixed mode)

    Perhaps now is the time to ensure this code is flexible enough to handle these future versions correctly, too?

  2. Shall we create some cram tests? For the most part, we could mock the directory/file structures in the test script. That way, Travis will tell us if our changes break anything. An argument against creating tests is that we plan to retire this launcher at some point relatively soon (#33). But then my vote would be to push harder on making that switch sooner rather than later. And actually, the tests may still be useful for verifying backward compatibility with the old launcher.
stelfrich commented 6 years ago

I have a couple of questions/concerns/ideas here:

Good questions! Thanks for keeping the broader perspective while I get lost in the details ;-)

Perhaps now is the time to ensure this code is flexible enough to handle these future versions correctly, too?

A quick check results in the exception(s) below. But that's an issue for ij1-patcher and not for the launcher since Java has been started properly at that point.

➜  Fiji.app_launcher ./imagej-launcher --java-home=/opt/jdk-10/
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by net.imagej.patcher.LegacyInjector (file:/opt/Fiji/Fiji.app_launcher/jars/ij1-patcher-0.12.6.jar) to method java.lang.ClassLoader.findLoadedClass(java.lang.String)
WARNING: Please consider reporting this to the maintainers of net.imagej.patcher.LegacyInjector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[ERROR] Invalid service: net.imagej.legacy.LegacyService
java.lang.RuntimeException: Failed to instantiate IJ1.
    at net.imagej.legacy.LegacyService.initialize(LegacyService.java:459)
    at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:353)
    at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
    at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:340)
    at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:194)
    at org.scijava.service.ServiceHelper.loadServices(ServiceHelper.java:166)
    at org.scijava.Context.<init>(Context.java:279)
    at org.scijava.Context.<init>(Context.java:235)
    at org.scijava.Context.<init>(Context.java:175)
    at org.scijava.Context.<init>(Context.java:161)
    at net.imagej.ImageJ.<init>(ImageJ.java:77)
    at net.imagej.Main.main(Main.java:54)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at net.imagej.launcher.ClassLauncher.launch(ClassLauncher.java:279)
    at net.imagej.launcher.ClassLauncher.run(ClassLauncher.java:186)
    at net.imagej.launcher.ClassLauncher.main(ClassLauncher.java:77)
Caused by: java.lang.IllegalArgumentException: Problem accessing ImageJ 1.x in class loader net.imagej.launcher.ClassLoaderPlus( ... )
    at net.imagej.patcher.LegacyEnvironment.isImageJ1Initialized(LegacyEnvironment.java:556)
    at net.imagej.legacy.LegacyService.initialize(LegacyService.java:452)
    ... 21 more
Caused by: java.lang.ExceptionInInitializerError
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at net.imagej.patcher.LegacyEnvironment.isImageJ1Initialized(LegacyEnvironment.java:553)
    ... 22 more
Caused by: java.lang.StringIndexOutOfBoundsException: begin 0, end 3, length 2
    at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3107)
    at java.base/java.lang.String.substring(String.java:1873)
    at ij.IJ.<clinit>(IJ.java:76)
    ... 27 more
[ERROR] No match: net.imagej.legacy.LegacyService
[ERROR] Invalid service: net.imagej.legacy.LegacyService
java.lang.RuntimeException: Failed to instantiate IJ1.
    at net.imagej.legacy.LegacyService.initialize(LegacyService.java:459)
    at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:353)
    at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:194)
    at org.scijava.service.ServiceHelper.loadServices(ServiceHelper.java:166)
    at org.scijava.Context.<init>(Context.java:279)
    at org.scijava.Context.<init>(Context.java:235)
    at org.scijava.Context.<init>(Context.java:175)
    at org.scijava.Context.<init>(Context.java:161)
    at net.imagej.ImageJ.<init>(ImageJ.java:77)
    at net.imagej.Main.main(Main.java:54)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at net.imagej.launcher.ClassLauncher.launch(ClassLauncher.java:279)
    at net.imagej.launcher.ClassLauncher.run(ClassLauncher.java:186)
    at net.imagej.launcher.ClassLauncher.main(ClassLauncher.java:77)
Caused by: java.lang.IllegalArgumentException: Problem accessing ImageJ 1.x in class loader net.imagej.launcher.ClassLoaderPlus( ... )
    at net.imagej.patcher.LegacyEnvironment.isImageJ1Initialized(LegacyEnvironment.java:556)
    at net.imagej.legacy.LegacyService.initialize(LegacyService.java:452)
    ... 18 more
Caused by: java.lang.NoClassDefFoundError: Could not initialize class ij.IJ
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at net.imagej.patcher.LegacyEnvironment.isImageJ1Initialized(LegacyEnvironment.java:553)
    ... 19 more
[ERROR] No match: net.imagej.legacy.LegacyService
[ERROR] Exception during event handling:
    [Event] org.scijava.service.event.ServicesLoadedEvent
    context = org.scijava.Context@78adaec6
    consumed = false
    [Subscriber] fiji.DefaultFijiService [priority = 0.0]
    [Method] protected void fiji.DefaultFijiService.onEvent(org.scijava.service.event.ServicesLoadedEvent)
java.lang.NoClassDefFoundError: Could not initialize class ij.IJ
    at fiji.DefaultFijiService.actuallyInitialize(DefaultFijiService.java:36)
    at fiji.DefaultFijiService.onEvent(DefaultFijiService.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.scijava.event.DefaultEventService$ProxySubscriber.onEvent(DefaultEventService.java:300)
    at org.scijava.event.DefaultEventService$ProxySubscriber.onEvent(DefaultEventService.java:274)
    at org.bushe.swing.event.ThreadSafeEventService.publish(ThreadSafeEventService.java:971)
    at org.scijava.event.DefaultEventBus.access$201(DefaultEventBus.java:56)
    at org.scijava.event.DefaultEventBus$2.run(DefaultEventBus.java:216)
    at org.scijava.thread.DefaultThreadService$2.run(DefaultThreadService.java:220)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:844)
java.lang.IllegalArgumentException: Required service is missing: net.imagej.legacy.LegacyService
Context: org.scijava.Context@78adaec6
ClassLoader: net.imagej.launcher.ClassLoaderPlus( ... )

-- Services known to context --
org.scijava.event.DefaultEventService [priority = 100000.0]
net.imagej.legacy.LegacyConsoleService [priority = 100.0]
net.imagej.legacy.display.LegacyImageDisplayService [priority = 100.0]
net.imagej.lut.DefaultLUTService [priority = 100.0]
org.scijava.script.DefaultScriptService [priority = 100.0]
io.scif.services.SCIFIODatasetService [priority = 1.0]
fiji.DefaultFijiService [priority = 0.0]
io.scif.DefaultMetadataService [priority = 0.0]
io.scif.codec.DefaultCodecService [priority = 0.0]
io.scif.formats.qt.DefaultQTJavaService [priority = 0.0]
io.scif.formats.tiff.DefaultTiffService [priority = 0.0]
io.scif.gui.DefaultGUIService [priority = 0.0]
io.scif.img.DefaultImgUtilityService [priority = 0.0]
io.scif.img.cell.cache.MapDBCache [priority = 0.0]
io.scif.img.converters.DefaultPlaneConverterService [priority = 0.0]
io.scif.io.DefaultNIOService [priority = 0.0]
io.scif.ome.services.DefaultOMEMetadataService [priority = 0.0]
io.scif.ome.services.DefaultOMEXMLService [priority = 0.0]
io.scif.refs.DefaultRefManagerService [priority = 0.0]
io.scif.services.DefaultDatasetIOService [priority = 0.0]
io.scif.services.DefaultFilePatternService [priority = 0.0]
io.scif.services.DefaultFormatService [priority = 0.0]
io.scif.services.DefaultLocationService [priority = 0.0]
io.scif.services.DefaultTranslatorService [priority = 0.0]
io.scif.services.JAIIIOServiceImpl [priority = 0.0]
io.scif.xml.DefaultXMLService [priority = 0.0]
net.imagej.DefaultDatasetService [priority = 0.0]
net.imagej.DefaultImgPlusService [priority = 0.0]
net.imagej.animation.DefaultAnimationService [priority = 0.0]
net.imagej.autoscale.DefaultAutoscaleService [priority = 0.0]
net.imagej.display.DefaultImageDisplayService [priority = 0.0]
net.imagej.display.DefaultOverlayService [priority = 0.0]
net.imagej.display.DefaultWindowService [priority = 0.0]
net.imagej.display.DefaultZoomService [priority = 0.0]
net.imagej.measure.DefaultMeasurementService [priority = 0.0]
net.imagej.measure.DefaultStatisticsService [priority = 0.0]
net.imagej.notebook.DefaultNotebookService [priority = 0.0]
net.imagej.operator.DefaultCalculatorService [priority = 0.0]
net.imagej.ops.DefaultNamespaceService [priority = 0.0]
net.imagej.ops.DefaultOpMatchingService [priority = 0.0]
net.imagej.ops.DefaultOpService [priority = 0.0]
net.imagej.sampler.DefaultSamplerService [priority = 0.0]
net.imagej.threshold.DefaultThresholdService [priority = 0.0]
net.imagej.types.DefaultDataTypeService [priority = 0.0]
net.imagej.ui.DefaultImageJUIService [priority = 0.0]
net.imagej.ui.awt.AWTRenderingService [priority = 0.0]
net.imagej.ui.awt.AWTScreenCaptureService [priority = 0.0]
net.imagej.ui.swing.ops.DefaultOpFinderService [priority = 0.0]
net.imagej.ui.swing.overlay.JHotDrawService [priority = 0.0]
net.imagej.units.DefaultUnitService [priority = 0.0]
net.imagej.updater.DefaultUpdateService [priority = 0.0]
net.imagej.updater.DefaultUploaderService [priority = 0.0]
org.scijava.app.DefaultAppService [priority = 0.0]
org.scijava.app.DefaultStatusService [priority = 0.0]
org.scijava.command.DefaultCommandService [priority = 0.0]
org.scijava.console.DefaultConsoleService [priority = 0.0]
org.scijava.convert.DefaultConvertService [priority = 0.0]
org.scijava.display.DefaultDisplayService [priority = 0.0]
org.scijava.event.DefaultEventHistory [priority = 0.0]
org.scijava.input.DefaultInputService [priority = 0.0]
org.scijava.io.DefaultDataHandleService [priority = 0.0]
org.scijava.io.DefaultIOService [priority = 0.0]
org.scijava.io.DefaultRecentFileService [priority = 0.0]
org.scijava.main.DefaultMainService [priority = 0.0]
org.scijava.menu.DefaultMenuService [priority = 0.0]
org.scijava.module.DefaultModuleService [priority = 0.0]
org.scijava.object.DefaultObjectService [priority = 0.0]
org.scijava.options.DefaultOptionsService [priority = 0.0]
org.scijava.parse.DefaultParseService [priority = 0.0]
org.scijava.platform.DefaultPlatformService [priority = 0.0]
org.scijava.plugin.DefaultPluginService [priority = 0.0]
org.scijava.prefs.DefaultPrefService [priority = 0.0]
org.scijava.run.DefaultRunService [priority = 0.0]
org.scijava.script.DefaultScriptHeaderService [priority = 0.0]
org.scijava.script.process.DefaultScriptProcessorService [priority = 0.0]
org.scijava.text.DefaultTextService [priority = 0.0]
org.scijava.thread.DefaultThreadService [priority = 0.0]
org.scijava.tool.DefaultToolService [priority = 0.0]
org.scijava.ui.DefaultUIService [priority = 0.0]
org.scijava.ui.dnd.DefaultDragAndDropService [priority = 0.0]
org.scijava.ui.swing.SwingIconService [priority = 0.0]
org.scijava.ui.swing.script.DefaultLanguageSupportService [priority = 0.0]
org.scijava.welcome.DefaultWelcomeService [priority = 0.0]
org.scijava.widget.DefaultWidgetService [priority = 0.0]
io.scif.services.DefaultInitializeService [priority = -100.0]
net.imagej.display.DummyScreenCaptureService [priority = -100.0]
net.imagej.render.DummyRenderingService [priority = -100.0]
org.scijava.log.StderrLogService [priority = -100.0]
org.scijava.platform.DefaultAppEventService [priority = -100.0]
org.scijava.cache.DefaultCacheService [priority = -10000.0]

-- Classpath of ClassLoader --
...

    at org.scijava.Context.inject(Context.java:472)
    at org.scijava.Context.inject(Context.java:384)
    at org.scijava.plugin.DefaultPluginService.createInstance(DefaultPluginService.java:237)
    at org.scijava.ui.DefaultUIService.discoverUIs(DefaultUIService.java:488)
    at org.scijava.ui.DefaultUIService.uiList(DefaultUIService.java:467)
    at org.scijava.ui.DefaultUIService.getDefaultUI(DefaultUIService.java:193)
    at org.scijava.ui.DefaultUIService.showUI(DefaultUIService.java:138)
    at org.scijava.AbstractGateway.launch(AbstractGateway.java:102)
    at net.imagej.Main.main(Main.java:55)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at net.imagej.launcher.ClassLauncher.launch(ClassLauncher.java:279)
    at net.imagej.launcher.ClassLauncher.run(ClassLauncher.java:186)
    at net.imagej.launcher.ClassLauncher.main(ClassLauncher.java:77)
Error while executing the main() method of class 'net.imagej.Main':
java.lang.NullPointerException
    at net.imagej.legacy.ui.LegacyUI.ij1Helper(LegacyUI.java:118)
    at net.imagej.legacy.ui.LegacyUI.show(LegacyUI.java:129)
    at org.scijava.ui.DefaultUIService.showUI(DefaultUIService.java:155)
    at org.scijava.ui.DefaultUIService.showUI(DefaultUIService.java:140)
    at org.scijava.AbstractGateway.launch(AbstractGateway.java:102)
    at net.imagej.Main.main(Main.java:55)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at net.imagej.launcher.ClassLauncher.launch(ClassLauncher.java:279)
    at net.imagej.launcher.ClassLauncher.run(ClassLauncher.java:186)
    at net.imagej.launcher.ClassLauncher.main(ClassLauncher.java:77)
stelfrich commented 6 years ago

Shall we create some cram tests?

We had talked about that for the launcher in a different context where it did not make too much sense (since I couldn't figure out how to run cram on Windows). We could write some tests for the Linux and macOS builds and run them with the respective binaries from the Travis builds. Won't work for Windows though (since cram doesn't really work there).

Could we use minimal containers with different JDK/JRE versions to test the launcher? Docker is supported on Travis CI as well as AppVeyor. This way, we would "only" have to add another image to test to the build matrix for future versions and we would get real feedback (although we might have to figure out how to best do that). Could also be useful for the new version of the launcher...