imagej / ij1-patcher

Extension points for ImageJ via runtime patching to support (limited) headless operation and ImageJ2's legacy layer
BSD 2-Clause "Simplified" License
5 stars 6 forks source link

Avoid confusion between ij.Macro class and ij.macro package #38

Open ctrueden opened 9 years ago

ctrueden commented 9 years ago

The following exception is emitted at startup of ImageJ2:

java.lang.IllegalArgumentException: Cannot handle replace call to show in ij.gui.StackWindow's public <init>(ij.ImagePlus imp, ij.gui.ImageCanvas ic)
    at net.imagej.patcher.CodeHacker.replaceCallInMethod(CodeHacker.java:725)
    at net.imagej.patcher.CodeHacker.replaceCallInMethod(CodeHacker.java:650)
    at net.imagej.patcher.LegacyInjector.inject(LegacyInjector.java:320)
    at net.imagej.patcher.LegacyInjector.injectHooks(LegacyInjector.java:109)
    at net.imagej.patcher.LegacyEnvironment.initialize(LegacyEnvironment.java:101)
    at net.imagej.patcher.LegacyEnvironment.applyPatches(LegacyEnvironment.java:495)
    at net.imagej.patcher.LegacyInjector.preinit(LegacyInjector.java:397)
    at net.imagej.patcher.LegacyInjector.preinit(LegacyInjector.java:376)
    at net.imagej.legacy.LegacyService.<clinit>(LegacyService.java:130)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.lang.Class.newInstance0(Class.java:357)
    at java.lang.Class.newInstance(Class.java:310)
    at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:302)
    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:267)
    at org.scijava.Context.<init>(Context.java:224)
    at org.scijava.Context.<init>(Context.java:163)
    at org.scijava.Context.<init>(Context.java:119)
    at org.scijava.Context.<init>(Context.java:107)
    at net.imagej.ImageJ.<init>(ImageJ.java:78)
    at net.imagej.Main.launch(Main.java:61)
    at net.imagej.Main.main(Main.java:73)
Caused by: java.lang.RuntimeException: cannot find ij.macro: ij.Macro found in ij/macro.class
    at javassist.CtClassType.getClassFile2(CtClassType.java:196)
    at javassist.CtClassType.makeFieldCache(CtClassType.java:867)
    at javassist.CtClassType.getMembers(CtClassType.java:858)
    at javassist.CtClassType.getDeclaredField2(CtClassType.java:992)
    at javassist.CtClassType.getField2(CtClassType.java:946)
    at javassist.CtClassType.getField(CtClassType.java:927)
    at javassist.CtClass.getField(CtClass.java:819)
    at javassist.compiler.MemberResolver.lookupFieldByJvmName2(MemberResolver.java:283)
    at javassist.compiler.TypeChecker.fieldAccess2(TypeChecker.java:913)
    at javassist.compiler.TypeChecker.fieldAccess(TypeChecker.java:870)
    at javassist.compiler.TypeChecker.atFieldRead(TypeChecker.java:803)
    at javassist.compiler.TypeChecker.atExpr(TypeChecker.java:578)
    at javassist.compiler.ast.Expr.accept(Expr.java:68)
    at javassist.compiler.TypeChecker.fieldAccess(TypeChecker.java:860)
    at javassist.compiler.TypeChecker.atFieldRead(TypeChecker.java:803)
    at javassist.compiler.TypeChecker.atExpr(TypeChecker.java:578)
    at javassist.compiler.ast.Expr.accept(Expr.java:68)
    at javassist.compiler.TypeChecker.booleanExpr(TypeChecker.java:523)
    at javassist.compiler.TypeChecker.atExpr(TypeChecker.java:592)
    at javassist.compiler.ast.Expr.accept(Expr.java:68)
    at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:242)
    at javassist.compiler.CodeGen.compileBooleanExpr(CodeGen.java:236)
    at javassist.compiler.CodeGen.atIfStmnt(CodeGen.java:384)
    at javassist.compiler.CodeGen.atStmnt(CodeGen.java:355)
    at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
    at javassist.compiler.Javac.compileStmnt(Javac.java:569)
    at javassist.expr.MethodCall.replace(MethodCall.java:235)
    at net.imagej.patcher.CodeHacker$7.edit(CodeHacker.java:686)
    at javassist.expr.ExprEditor.loopBody(ExprEditor.java:192)
    at javassist.expr.ExprEditor.doit(ExprEditor.java:91)
    at javassist.CtBehavior.instrument(CtBehavior.java:712)
    at net.imagej.patcher.CodeHacker$EagerExprEditor.instrument(CodeHacker.java:1278)
    at net.imagej.patcher.CodeHacker.replaceCallInMethod(CodeHacker.java:670)
    ... 30 more

I think the offending line is here. Maybe it's a bug in Javassist; I'm not sure. Regardless, we can probably fix it by avoiding a hard reference on the ij.macro package in favor of using reflection or indirection (perhaps a LegacyHooks#isBatchMode() method?).

dscho commented 9 years ago

The real question is: where does that bogus macro.class come from.

ctrueden commented 8 years ago

OK, I keep running across this, once every couple of months, and then forget to write down the cause: it happens in Eclipse if the net.imagej:ij is also open and project linked to the component being run. This can happen quite frequently with ij specifically because its master branch is typically at a release version in the POM—usually the latest, which often matches the component under active development.

I am guessing the problem only occurs on case-insensitive file systems—in my case, HFS+ on OS X. Javassist finds Macro.class—which can be referenced just as well as macro.class on such file systems—and gets confused.

Anyway, since there is an easy workaround, fixing this is pretty darn low priority.