Login  Register

Correction Re: Problem: Multiple uses of Compile and Run. [was: Strange ClassCastException...]

Posted by Bill Mohler on May 04, 2009; 7:34pm
URL: http://imagej.273.s1.nabble.com/Strange-ClassCastException-A-puzzle-for-Java-ImageJ-experts-to-help-me-wit-tp3692688p3692691.html

At 3:20 PM -0400 5/4/09, Bill Mohler wrote:

>Dear ImageJers (especially Wayne, Curtis, and Dscho)
>
>I ultimately confirmed that my trouble with ClassCastExceptions
>arises when I try to have two different plugins, each individually
>launched using compile and run, address the same plugin-based class
>extending ImageStack.
>
>I get the same problem with either of two versions of 1.42o that
>Wayne sent me. And the problem goes away if the plugins are compiled
>and installed from a jar file. Interestingly, the order in which
>they are opened using Compile & Run matters as to whether I see the
>problem or not:
>
>StackOpener first, pluginFrame controller second => exception. (but
>not if installed from jar or from precompiled class containing _ in
>name.)

SORRY! I had the nextline wrong in my last email! Not trying to add
to confusion.

>pluginFrame controller first, StackOpener second => exception.


>
>Each use of Compile and Run creates a new class loader, and this can
>cause conflicts due to multiple instances of the loaded class.
>
>** Compile and Run of the StackOpener always builds a window which
>fails to be controlled by the pluginFrame, whether the pluginFrame
>was precompiled or loaded by Compile & Run.
>
>If both are precompiled and installed, the order in which they were
>instantiated does not matter. Everything works fine.
>
>FYI I have been ping-ponging between the code for both classes and
>moving methods from one to the other as I develop how they interact.
>It's for this reason that I tend to load them sequentially with C&R
>during the same ImageJ session. Maybe I should grow up and setup the
>project in an IDE.
>
>Perhaps Wayne or someone can give a better idea of why this happens
>with Compile and Run and whether it can be fixed in any way. It's
>easy enough to avoid now that I know it's a hazard. But I'm not sure
>if others might be experiencing class loader problems with Compile
>and Run but not knowing it.
>
>Bill
>
>>A little bit more info. I read up on class loaders, and decided to
>>look at their parentage.
>>
>>It looks life all of the class loaders that pop up are direct
>>descendents of the system class loader. I don't know if this gives
>>me any further ability to control what's going on.
>>
>>Bill
>>
>>I put the class loader finding code block in 3 different places
>>
>>First, in the "opener" plugin that gets a list of movies from the
>>user and then builds the MQTVS as an object called vstack:
>>
>>From QT_M_OMM.cSTHS
>>vstack loader = ij.io.PluginClassLoader@4eabb
>>vstack loader parent= sun.misc.Launcher$AppClassLoader@a39137
>>mqtvs loader = ij.io.PluginClassLoader@4eabb
>>mqtvs loader parent = sun.misc.Launcher$AppClassLoader@a39137
>>Loaders equal? true/true
>>system loader = sun.misc.Launcher$AppClassLoader@a39137
>>system loader parent = sun.misc.Launcher$ExtClassLoader@858610
>>ImageJ loader = ij.io.PluginClassLoader@4eabb
>>ImageJ loader parent = sun.misc.Launcher$AppClassLoader@a39137
>>
>>Then in the MQTVS class's getProcessor() method that figures out
>>which images to display:
>>
>>From MQTVS.gP
>>stack loader = sun.misc.Launcher$AppClassLoader@a39137
>>stack loader parent= sun.misc.Launcher$ExtClassLoader@858610
>>mqtvs loader = ij.io.PluginClassLoader@4eabb
>>mqtvs loader parent = sun.misc.Launcher$AppClassLoader@a39137
>>Loaders equal? false/false
>>system loader = sun.misc.Launcher$AppClassLoader@a39137
>>system loader parent = sun.misc.Launcher$ExtClassLoader@858610
>>ImageJ loader = ij.io.PluginClassLoader@4eabb
>>ImageJ loader parent = sun.misc.Launcher$AppClassLoader@a39137
>>
>>**Interesting note: this getProcessor() gets called once even
>>BEFORE the method far above gets called.  Then this  is also called
>>many times later.  In both the first and then the subsequent calls,
>>it always reports the loaders as shown here.
>>
>>Then in the PluginFrame adjustmentValueChanged() method that I've
>>been bashing about all afternoon:
>>
>>From MAFMOD.aVC
>>stack loader = ij.io.PluginClassLoader@4eabb
>>stack loader parent= sun.misc.Launcher$AppClassLoader@a39137
>>mqtvs loader = ij.io.PluginClassLoader@c68b6f
>>mqtvs loader parent = sun.misc.Launcher$AppClassLoader@a39137
>>Loaders equal? false/false
>>system loader = sun.misc.Launcher$AppClassLoader@a39137
>>system loader parent = sun.misc.Launcher$ExtClassLoader@858610
>>ImageJ loader = ij.io.PluginClassLoader@c68b6f
>>ImageJ loader parent = sun.misc.Launcher$AppClassLoader@a39137
>>
>>
>>
>>Somehow, it looks like this object gets handled first by the ImageJ
>>loader in the "opener", then it (or a copy/clone?) gets handed off
>>to the system loader in MQTVS, then it ends up in the hands of a
>>third loader (neither system not ImageJ) in the PluginFrame. It
>>looks life all of the class loaders that pop up are direct
>>descendents of the system class loader.
>>
>>Fascinated, but more perplexed than ever.
>>
>>Thanks to Dscho and Curtis,
>>Bill
>>
>>>Hi Bill,
>>>
>>>I agree with Dscho that it must be two ClassLoaders, each with their own
>>>version of the class. I have never heard of this happening before, but it is
>>>conceivable, since ImageJ uses its own ClassLoader, and maybe QTJava does
>>>too (not sure).
>>>
>>>Try this code:
>>>
>>>ClassLoader stackLoader = stack.getClass().getClassLoader();
>>>ClassLoader mqtvsLoader = MultiQTVirtualStack.class.getClassLoader();
>>>IJ.log("stack loader = " + stackLoader);
>>>IJ.log("mqtvs loader = " + mqtvsLoader);
>>>IJ.log("Loaders equal? " + (stackLoader == mqtvsLoader) + "/" +
>>>stackLoader.equals(mqtvsLoader));
>>>ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
>>>ClassLoader ijLoader = ij.IJ.getClassLoader();
>>>IJ.log("system loader = " + systemLoader);
>>>IJ.log("ImageJ loader = " + ijLoader);
>>>
>>>Check whether the numerical codes for the stack & mqtvs loaders line up with
>>>the system and/or ImageJ loaders. Then you'll know which class loader is
>>>loading which version of the class. But ultimately, this bug may not be
>>>something easily fixed within your code -- it may require a change to
>>>ImageJ. Not sure without further messing around...
>>>
>>>-Curtis
>>>
>>>On Wed, Apr 29, 2009 at 11:06 AM, Johannes Schindelin <
>>>[hidden email]> wrote:
>>>
>>>>  Hi,
>>>>
>>>>  On Wed, 29 Apr 2009, Bill Mohler wrote:
>>>>
>>>>  > Thanks, Curtis.  Here's what I get
>>>>  >
>>>>  > MultiQTVirtualStack1
>>>>  > stack class = MultiQTVirtualStack
>>>>  > MultiQTVirtualStack class = MultiQTVirtualStack
>>>>  > Classes equal? false/false
>>>>  > path to MultiQTVirtualStack class =
>>>>  >
>>>>
>>>>file:/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MultiQTVirtualStack.class
>>>>  > path to stack class =
>>>>  >
>>>>
>>>>file:/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MultiQTVirtualStack.class
>>>>  > beforetheloop imp[3-Movie Overlay #1 : see Log window for details
>>>>  > 600x411x38961]
>>>>  > stack[600x411x38961]
>>>>  > intheloop j= 0 imp[3-Movie Overlay #1 : see Log window for details
>>>>  > 600x411x38961]
>>>>  > stack[600x411x38961]
>>>>  > MultiQTVirtualStack2
>>>>  > MultiQTVirtualStack3
>>>>  >
>>>>  >
>>>>  > So, mysteriously to me, the code you sent reports that they
>>>>are NOT equal
>>>>  > classes.  However both paths point to the same class file!
>>>  >
>>>>  Then I am pretty certain that two different class loaders are competing
>>>>  for the class.
>>>>
>>>>  Could you print ...getClass().getClassLoader(), too?
>>>>
>>>>  Ciao,
>>>>  Dscho


--
-----------------
William A. Mohler
Associate Professor
Dept. of Genetics and Developmental Biology
University of Connecticut Health Center
MC-3301
263 Farmington Ave.
Farmington, CT   06030-3301

[hidden email]
Mobile: (860) 985-2719
alt. mobile: (860) 331-8514
skype: wmohler

Office: (860) 679-1833, room E2029
Lab: (860) 679-1834, room E2032
Fax: (314) 689-1833

G&DB dept. ofc.: (860) 679-8350
G&DB dept. fax : (860) 679-8345
http://genetics.uchc.edu/Faculty/Mohler/Mohler.html