Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
I hope that some of you with time and experience can help me with a
suggestion.  Please take some time, if you have a chance, to work
through the details I'm providing below:

I have created a new class called MultiQTVirtualStack (MQTVS for
short here), spinning off of the success of Jeffrey Woodard's
QTVirtualStack (QTVS for short here, which makes working with
QuickTime movies in a true ImageJ StackWindow a delight).

MQTVS extends VirtualStack (and therefore ImageStack) and allows the
user to open a collection of QTVSs into a single Virtual HyperStack
window, in which each QTVS plays as a separate channel, but all the
QTVS-derived channels are navigated synchronously in the Z and T
dimensions.  The window can be viewed in either Composite (color
overlay), Color (separate channel), or Grayscale (separate channel)
modes that are available for HyperStacks.  This all works nicely now
for me.  Happy to share the code, but it's not cleaned up pretty yet.

Now I am trying to create a PluginFrame with which the user can shift
the registration of the Z and T dimensions of the various QTVS
channels of the MQTVS window, so as to better synchronize movies that
were collected separately and may start at different relative times
during an event of interest that needs to be compared.

I have previously created methods MQTVS.adjustSingleMovieZ(int
channel, boolean forward) and MQTVS.adjustSingleMovieT(int channel,
boolean forward), which in turn call methods in my modified version
of QTVS to rearrange the order of elements in the ArrayList,
frameLocations, pointing to movie frames by a single position in
either Z or T.  This interaction of methods has worked well for me
when I code "for" loops that make a fixed number of calls to the
MQTVS.adjustSingleMovie...() methods from within the constructor of
MQTVS (an experimental proof of principal that works very nicely).
Here are the methods themselves, isolated from the rest of their
classes for simplicity.  The problems I'm having in calling these
methods via a PluginFrame are described below.

 From MQTVS:
   /*These methods allow viewer to shift the Z or T positions of a
given channel to better synchronize movies.*/
        public void adjustSingleMovieZ(int channel, boolean forward) {
                this.forward = forward;
                ((QTVirtualStack) stack[channel]).shiftMovieZ(forward);
                IJ.log("got to MQTVS.ASMZ");

        }

        public void adjustSingleMovieT(int channel, boolean forward) {
                this.forward = forward;
                ((QTVirtualStack) stack[channel]).shiftMovieT(forward);

        }


 From QTVS:
   /*These methods allow viewer to shift the Z or T positions of a
given channel to better synchronize movies.*/
        public void shiftMovieT(boolean forward) {
                this.forward = forward;
                if (!forward) {
                        for (int z = 0; z < maxSlicesSingleMovie ; z++) {
                                this.frameLocations.add( (z*
maxTimesSingleMovie) , this.frameLocations.get( ((z+1)*
maxTimesSingleMovie) -1) );
                                this.frameLocations.remove(  ((z+1)*
maxTimesSingleMovie) -1 );
                        }
                } else {
                        for (int z = maxSlicesSingleMovie-1 ; z >= 0  ; z--) {
                                this.frameLocations.add( ((z+1)*
maxTimesSingleMovie-1) , this.frameLocations.get( (z)*
maxTimesSingleMovie ));
                                this.frameLocations.remove( ((z)*
maxTimesSingleMovie ) );
                        }
                }
        }

        public void shiftMovieZ(boolean forward) {

                this.forward = forward;
                ArrayList copyFrames = new ArrayList();
                IJ.log("Got to the QTVS.SMZ");

                if (forward) {
                        for (int t= 0; t < maxTimesSingleMovie; t++) {
                                copyFrames.add(
this.frameLocations.get(((maxSlicesSingleMovie-1)*maxTimesSingleMovie)
) );
 
        this.frameLocations.remove(((maxSlicesSingleMovie-1)*maxTimesSingleMovie)
);
                        }
                        this.frameLocations.addAll(0, copyFrames);
                } else {
                        for (int t= 0; t < maxTimesSingleMovie; t++) {
                                copyFrames.add( this.frameLocations.get(0) );
                                this.frameLocations.remove(0);
                        }
                        this.frameLocations.addAll(copyFrames);
                }

        }



**Now to the problems I am having (apparently at the level of the JVM??).
Here I try to call the public method MQTVS.adjustSingleMovieZ(int
channel, boolean forward), sending parameters set by the user in the
slider of the PluginFrame.  I have no problems compiling, and get no
exceptions reported in the log window of ImageJ.  But (thanks to help
from Wayne), I find a ClassCastException from the event dispatch
thread in the console.  The confusion comes in the apparent
correctness of the type of a variable that I assign with the
ImagePlus.getStack() command, but the wrongness of how the event
dispatch thread deals with the variable when I try to cast it to its
true type (I think). First I show the code from the method in the
PluginFrame that reads the value of sliders and should call
MQTVS.adjustSingleMovieZ(int channel, boolean forward) to change a
specific QTVS's frame position being displayed.  Then below the code,
I show the IJ.log output from several lines in the method, and then
the ClassCastException from the console.

The key method from my PluginFrame MovieAlignFrameMOD:
     public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
        ImagePlus imp = WindowManager.getCurrentImage();

        ImageStack stack = imp.getStack();
        IJ.log(""+stack.getClass().getName() + "1");

        ImageWindow win = imp.getWindow();
        int zImpPos = imp.getSlice();
        int tImpPos = imp.getFrame();
        IJ.log("beforetheloop " +  imp+" \n" + imp.getStack()) ;
        boolean forward = false;

        if (imp==null) return;
                for (int i=0; i< imp.getNChannels(); i++){
                        if (e.getSource()==sliceShifter[i]) {
                                int zShiftLive = sliceShifter[i].getValue();
                                int zShiftNet = zShiftLive - previousShiftZ[i];
                                int zShiftNetAbs = zShiftNet;
                                if (zShiftNet < 0) {
                                        zShiftNetAbs = -zShiftNet;
                                        forward = true;
                                }
                                previousShiftZ[i] = previousShiftZ[i]
+ zShiftNet;

                                for(int j = 0; j < zShiftNetAbs; j++){
                                        IJ.log("intheloop j= " + j +
" " + imp+" \n" + imp.getStack()) ;  
 
        IJ.log(""+stack.getClass().getName() + "2");

                        /** THIS DOES NOT REPORT, SO IT'S CLEAR THAT
stack IS NOT reporting as instanceof MultiQTVirtualStack,
                        even though it reports as one using
stack.getClass().getName() **/
                                        if (stack instanceof
MultiQTVirtualStack ) IJ.log("MultiQTVirtualStack? Yes!!!!");

                        /*** ...But THIS STILL READS OUT AS
MultiQTVirtualStack  ******/
 
        IJ.log(""+stack.getClass().getName() + "3");

                        /**** THIS GIVES A "SILENT"
ClassCastException ON THE EVENT DISPATCH THREAD, CAN SEE IN CONSOLE
*****/
        /* LINE 289 */ ((MultiQTVirtualStack)
stack).adjustSingleMovieZ(i, forward);

                        /***** Once the exception has been thrown,
this next log statement fails to run ***********/
 
        IJ.log(""+stack.getClass().getName() + "4");

                                }

                        }
                        else if (e.getSource()==frameShifter[i]) {
                                int tShiftLive = frameShifter[i].getValue();
                                int tShiftNet = tShiftLive - previousShiftT[i];
                                previousShiftT[i] = tShiftNet;
                        /****** THE ACTIONS OF THIS IF CONDITION WILL
BE FILLED IN LATER ONCE I FIGURE OUT OTHER PROBLEMS ********/

                        }
                        notify();
                }
        }
     }



Here's what is logged by the IJ.log() statements above during a
slider adjustment:

MultiQTVirtualStack1
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


!!Note that I did not leave out the 4th log statement in copying.
The CCE apparently blocks the ability to run the 4th IJ.log statement
after line 289.  Also, the instanceof test fails (even before line
289), because I don't get the "MultiQTVirtualStack? Yes!!!" log
printed.


Finally, this is the exception from the event dispatch thread at the
critical line 289:

4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException:
MultiQTVirtualStack
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
MovieAlignFrameMOD.adjustmentValueChanged(MovieAlignFrameMOD.java:289)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.Scrollbar.processAdjustmentEvent(Scrollbar.java:1094)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.Scrollbar.processEvent(Scrollbar.java:1061)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.Component.dispatchEventImpl(Component.java:4068)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.Component.dispatchEvent(Component.java:3903)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)



In summary, I seem to have an object called stack returned to me by
ImagePlus.getStack() which both is a MultiQTVirtualStack by some
tests and is NOT a MultiQTVirtualStack by others, and these other
criteria are what I really need to make my PluginFrame work.

Can anyone give me a hint of an explanation of what is going on here?
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

ctrueden
Hi Bill,

That's a devilish problem. Normally, the message printed in the
ClassCastException is the actual (incompatible) class of the object in
question. So it would appear that your object's class is
MultiQTVirtualStack, but somehow a different MultiQTVirtualStack than the
one you are referencing in code.

The only way I know for that to happen would be if the two classes have
different packages, which would happen if you have an import statement at
the top of your class. For example, let's say there's a
foo.bar.MultiQTVirtualStack in your classpath. If your code has a line
"import foo.bar.*;" on top, you might have the problem you're seeing.

Try adding the following debugging code:

Class stackClass = stack.getClass();
Class mqtvsClass = MultiQTVirtualStack.class;
IJ.log("stack class = " + stackClass.getName());
IJ.log("MultiQTVirtualStack class = " + mqtvsClass.getName());
IJ.log("Classes equal? " + (stackClass == mqtvsClass) + "/" +
stackClass.equals(mqtvsClass));
IJ.log("path to MultiQTVirtualStack class = " +
mqtvsClass.getResource(mqtvsClass.getName() + ".class"));
IJ.log("path to stack class = " +
stackClass.getResource(stackClass.getName() + ".class"));

Let us know what you find out!

-Curtis

On Wed, Apr 29, 2009 at 9:50 AM, Bill Mohler <[hidden email]>wrote:

> I hope that some of you with time and experience can help me with a
> suggestion.  Please take some time, if you have a chance, to work through
> the details I'm providing below:
>
> I have created a new class called MultiQTVirtualStack (MQTVS for short
> here), spinning off of the success of Jeffrey Woodard's QTVirtualStack (QTVS
> for short here, which makes working with QuickTime movies in a true ImageJ
> StackWindow a delight).
>
> MQTVS extends VirtualStack (and therefore ImageStack) and allows the user
> to open a collection of QTVSs into a single Virtual HyperStack window, in
> which each QTVS plays as a separate channel, but all the QTVS-derived
> channels are navigated synchronously in the Z and T dimensions.  The window
> can be viewed in either Composite (color overlay), Color (separate channel),
> or Grayscale (separate channel) modes that are available for HyperStacks.
>  This all works nicely now for me.  Happy to share the code, but it's not
> cleaned up pretty yet.
>
> Now I am trying to create a PluginFrame with which the user can shift the
> registration of the Z and T dimensions of the various QTVS channels of the
> MQTVS window, so as to better synchronize movies that were collected
> separately and may start at different relative times during an event of
> interest that needs to be compared.
>
> I have previously created methods MQTVS.adjustSingleMovieZ(int channel,
> boolean forward) and MQTVS.adjustSingleMovieT(int channel, boolean forward),
> which in turn call methods in my modified version of QTVS to rearrange the
> order of elements in the ArrayList, frameLocations, pointing to movie frames
> by a single position in either Z or T.  This interaction of methods has
> worked well for me when I code "for" loops that make a fixed number of calls
> to the MQTVS.adjustSingleMovie...() methods from within the constructor of
> MQTVS (an experimental proof of principal that works very nicely). Here are
> the methods themselves, isolated from the rest of their classes for
> simplicity.  The problems I'm having in calling these methods via a
> PluginFrame are described below.
>
> From MQTVS:
>  /*These methods allow viewer to shift the Z or T positions of a given
> channel to better synchronize movies.*/
>        public void adjustSingleMovieZ(int channel, boolean forward) {
>                this.forward = forward;
>                ((QTVirtualStack) stack[channel]).shiftMovieZ(forward);
>                IJ.log("got to MQTVS.ASMZ");
>
>        }
>
>        public void adjustSingleMovieT(int channel, boolean forward) {
>                this.forward = forward;
>                ((QTVirtualStack) stack[channel]).shiftMovieT(forward);
>
>        }
>
>
> From QTVS:
>  /*These methods allow viewer to shift the Z or T positions of a given
> channel to better synchronize movies.*/
>        public void shiftMovieT(boolean forward) {
>                this.forward = forward;
>                if (!forward) {
>                        for (int z = 0; z < maxSlicesSingleMovie ; z++) {
>                                this.frameLocations.add( (z*
> maxTimesSingleMovie) , this.frameLocations.get( ((z+1)* maxTimesSingleMovie)
> -1) );
>                                this.frameLocations.remove(  ((z+1)*
> maxTimesSingleMovie) -1 );
>                        }
>                } else {
>                        for (int z = maxSlicesSingleMovie-1 ; z >= 0  ; z--)
> {
>                                this.frameLocations.add( ((z+1)*
> maxTimesSingleMovie-1) , this.frameLocations.get( (z)* maxTimesSingleMovie
> ));
>                                this.frameLocations.remove( ((z)*
> maxTimesSingleMovie ) );
>                        }
>                }
>        }
>
>        public void shiftMovieZ(boolean forward) {
>
>                this.forward = forward;
>                ArrayList copyFrames = new ArrayList();
>                IJ.log("Got to the QTVS.SMZ");
>
>                if (forward) {
>                        for (int t= 0; t < maxTimesSingleMovie; t++) {
>                                copyFrames.add(
> this.frameLocations.get(((maxSlicesSingleMovie-1)*maxTimesSingleMovie) ) );
>
>
>  this.frameLocations.remove(((maxSlicesSingleMovie-1)*maxTimesSingleMovie)
> );
>                        }
>                        this.frameLocations.addAll(0, copyFrames);
>                } else {
>                        for (int t= 0; t < maxTimesSingleMovie; t++) {
>                                copyFrames.add( this.frameLocations.get(0)
> );
>                                this.frameLocations.remove(0);
>                        }
>                        this.frameLocations.addAll(copyFrames);
>                }
>
>        }
>
>
>
> **Now to the problems I am having (apparently at the level of the JVM??).
> Here I try to call the public method MQTVS.adjustSingleMovieZ(int channel,
> boolean forward), sending parameters set by the user in the slider of the
> PluginFrame.  I have no problems compiling, and get no exceptions reported
> in the log window of ImageJ.  But (thanks to help from Wayne), I find a
> ClassCastException from the event dispatch thread in the console.  The
> confusion comes in the apparent correctness of the type of a variable that I
> assign with the ImagePlus.getStack() command, but the wrongness of how the
> event dispatch thread deals with the variable when I try to cast it to its
> true type (I think). First I show the code from the method in the
> PluginFrame that reads the value of sliders and should call
> MQTVS.adjustSingleMovieZ(int channel, boolean forward) to change a specific
> QTVS's frame position being displayed.  Then below the code, I show the
> IJ.log output from several lines in the method, and then the
> ClassCastException from the console.
>
> The key method from my PluginFrame MovieAlignFrameMOD:
>    public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
>        ImagePlus imp = WindowManager.getCurrentImage();
>
>        ImageStack stack = imp.getStack();
>        IJ.log(""+stack.getClass().getName() + "1");
>
>        ImageWindow win = imp.getWindow();
>        int zImpPos = imp.getSlice();
>        int tImpPos = imp.getFrame();
>        IJ.log("beforetheloop " +  imp+" \n" + imp.getStack()) ;
>        boolean forward = false;
>
>        if (imp==null) return;
>                for (int i=0; i< imp.getNChannels(); i++){
>                        if (e.getSource()==sliceShifter[i]) {
>                                int zShiftLive = sliceShifter[i].getValue();
>                                int zShiftNet = zShiftLive -
> previousShiftZ[i];
>                                int zShiftNetAbs = zShiftNet;
>                                if (zShiftNet < 0) {
>                                        zShiftNetAbs = -zShiftNet;
>                                        forward = true;
>                                }
>                                previousShiftZ[i] = previousShiftZ[i] +
> zShiftNet;
>
>                                for(int j = 0; j < zShiftNetAbs; j++){
>                                        IJ.log("intheloop j= " + j + " " +
> imp+" \n" + imp.getStack()) ;
>        IJ.log(""+stack.getClass().getName() + "2");
>
>                        /** THIS DOES NOT REPORT, SO IT'S CLEAR THAT stack
> IS NOT reporting as instanceof MultiQTVirtualStack,
>                        even though it reports as one using
> stack.getClass().getName() **/
>                                        if (stack instanceof
> MultiQTVirtualStack ) IJ.log("MultiQTVirtualStack? Yes!!!!");
>
>                        /*** ...But THIS STILL READS OUT AS
> MultiQTVirtualStack  ******/
>
>        IJ.log(""+stack.getClass().getName() + "3");
>
>                        /**** THIS GIVES A "SILENT" ClassCastException ON
> THE EVENT DISPATCH THREAD, CAN SEE IN CONSOLE *****/
>        /* LINE 289 */                  ((MultiQTVirtualStack)
> stack).adjustSingleMovieZ(i, forward);
>
>                        /***** Once the exception has been thrown, this next
> log statement fails to run ***********/
>
>        IJ.log(""+stack.getClass().getName() + "4");
>
>                                }
>
>                        }
>                        else if (e.getSource()==frameShifter[i]) {
>                                int tShiftLive = frameShifter[i].getValue();
>                                int tShiftNet = tShiftLive -
> previousShiftT[i];
>                                previousShiftT[i] = tShiftNet;
>                        /****** THE ACTIONS OF THIS IF CONDITION WILL BE
> FILLED IN LATER ONCE I FIGURE OUT OTHER PROBLEMS ********/
>
>                        }
>                        notify();
>                }
>        }
>    }
>
>
>
> Here's what is logged by the IJ.log() statements above during a slider
> adjustment:
>
> MultiQTVirtualStack1
> 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
>
>
> !!Note that I did not leave out the 4th log statement in copying. The CCE
> apparently blocks the ability to run the 4th IJ.log statement after line
> 289.  Also, the instanceof test fails (even before line 289), because I
> don't get the "MultiQTVirtualStack? Yes!!!" log printed.
>
>
> Finally, this is the exception from the event dispatch thread at the
> critical line 289:
>
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] Exception in
> thread "AWT-EventQueue-0" java.lang.ClassCastException: MultiQTVirtualStack
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> MovieAlignFrameMOD.adjustmentValueChanged(MovieAlignFrameMOD.java:289)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.Scrollbar.processAdjustmentEvent(Scrollbar.java:1094)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.Scrollbar.processEvent(Scrollbar.java:1061)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.Component.dispatchEventImpl(Component.java:4068)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.Component.dispatchEvent(Component.java:3903)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
> 4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
> java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
>
>
>
> In summary, I seem to have an object called stack returned to me by
> ImagePlus.getStack() which both is a MultiQTVirtualStack by some tests and
> is NOT a MultiQTVirtualStack by others, and these other criteria are what I
> really need to make my PluginFrame work.
>
> Can anyone give me a hint of an explanation of what is going on here?
>
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
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!
Could it be that they are each actually derived from a different
constructor in the class?

   public MultiQTVirtualStack(QTFile[] mqtf, boolean eightBit) {

   public MultiQTVirtualStack(QTFile[] mqtf, boolean eightBit,
ImagePlus imp, boolean stretchToFitOverlay) {

I didn't think that imp.getStack() would call the constructor....

Still baffled, but with a bit more data!

Bill

>Hi Bill,
>
>That's a devilish problem. Normally, the message printed in the
>ClassCastException is the actual (incompatible) class of the object in
>question. So it would appear that your object's class is
>MultiQTVirtualStack, but somehow a different MultiQTVirtualStack than the
>one you are referencing in code.
>
>The only way I know for that to happen would be if the two classes have
>different packages, which would happen if you have an import statement at
>the top of your class. For example, let's say there's a
>foo.bar.MultiQTVirtualStack in your classpath. If your code has a line
>"import foo.bar.*;" on top, you might have the problem you're seeing.
>
>Try adding the following debugging code:
>
>Class stackClass = stack.getClass();
>Class mqtvsClass = MultiQTVirtualStack.class;
>IJ.log("stack class = " + stackClass.getName());
>IJ.log("MultiQTVirtualStack class = " + mqtvsClass.getName());
>IJ.log("Classes equal? " + (stackClass == mqtvsClass) + "/" +
>stackClass.equals(mqtvsClass));
>IJ.log("path to MultiQTVirtualStack class = " +
>mqtvsClass.getResource(mqtvsClass.getName() + ".class"));
>IJ.log("path to stack class = " +
>stackClass.getResource(stackClass.getName() + ".class"));
>
>Let us know what you find out!
>
>-Curtis
>
>On Wed, Apr 29, 2009 at 9:50 AM, Bill Mohler <[hidden email]>wrote:
>
>>  I hope that some of you with time and experience can help me with a
>>  suggestion.  Please take some time, if you have a chance, to work through
>>  the details I'm providing below:
>>
>>  I have created a new class called MultiQTVirtualStack (MQTVS for short
>>  here), spinning off of the success of Jeffrey Woodard's QTVirtualStack (QTVS
>>  for short here, which makes working with QuickTime movies in a true ImageJ
>>  StackWindow a delight).
>>
>>  MQTVS extends VirtualStack (and therefore ImageStack) and allows the user
>>  to open a collection of QTVSs into a single Virtual HyperStack window, in
>>  which each QTVS plays as a separate channel, but all the QTVS-derived
>>  channels are navigated synchronously in the Z and T dimensions.  The window
>>  can be viewed in either Composite (color overlay), Color (separate channel),
>>  or Grayscale (separate channel) modes that are available for HyperStacks.
>>   This all works nicely now for me.  Happy to share the code, but it's not
>>  cleaned up pretty yet.
>>
>>  Now I am trying to create a PluginFrame with which the user can shift the
>>  registration of the Z and T dimensions of the various QTVS channels of the
>>  MQTVS window, so as to better synchronize movies that were collected
>>  separately and may start at different relative times during an event of
>>  interest that needs to be compared.
>>
>>  I have previously created methods MQTVS.adjustSingleMovieZ(int channel,
>>  boolean forward) and MQTVS.adjustSingleMovieT(int channel, boolean forward),
>  > which in turn call methods in my modified version of QTVS to rearrange the
>>  order of elements in the ArrayList, frameLocations, pointing to movie frames
>>  by a single position in either Z or T.  This interaction of methods has
>  > worked well for me when I code "for" loops that make a fixed
>number of calls
>>  to the MQTVS.adjustSingleMovie...() methods from within the constructor of
>>  MQTVS (an experimental proof of principal that works very nicely). Here are
>>  the methods themselves, isolated from the rest of their classes for
>>  simplicity.  The problems I'm having in calling these methods via a
>>  PluginFrame are described below.
>>
>>  From MQTVS:
>>   /*These methods allow viewer to shift the Z or T positions of a given
>>  channel to better synchronize movies.*/
>>         public void adjustSingleMovieZ(int channel, boolean forward) {
>>                 this.forward = forward;
>>                 ((QTVirtualStack) stack[channel]).shiftMovieZ(forward);
>>                 IJ.log("got to MQTVS.ASMZ");
>>
>>         }
>>
>>         public void adjustSingleMovieT(int channel, boolean forward) {
>>                 this.forward = forward;
>>                 ((QTVirtualStack) stack[channel]).shiftMovieT(forward);
>>
>>         }
>>
>>
>>  From QTVS:
>>   /*These methods allow viewer to shift the Z or T positions of a given
>>  channel to better synchronize movies.*/
>>         public void shiftMovieT(boolean forward) {
>>                 this.forward = forward;
>>                 if (!forward) {
>>                         for (int z = 0; z < maxSlicesSingleMovie ; z++) {
>>                                 this.frameLocations.add( (z*
>>  maxTimesSingleMovie) , this.frameLocations.get( ((z+1)* maxTimesSingleMovie)
>>  -1) );
>>                                 this.frameLocations.remove(  ((z+1)*
>>  maxTimesSingleMovie) -1 );
>>                         }
>>                 } else {
>>                         for (int z = maxSlicesSingleMovie-1 ; z >= 0  ; z--)
>>  {
>>                                 this.frameLocations.add( ((z+1)*
>>  maxTimesSingleMovie-1) , this.frameLocations.get( (z)* maxTimesSingleMovie
>>  ));
>>                                 this.frameLocations.remove( ((z)*
>>  maxTimesSingleMovie ) );
>>                         }
>>                 }
>>         }
>>
>>         public void shiftMovieZ(boolean forward) {
>>
>>                 this.forward = forward;
>>                 ArrayList copyFrames = new ArrayList();
>>                 IJ.log("Got to the QTVS.SMZ");
>>
>>                 if (forward) {
>>                         for (int t= 0; t < maxTimesSingleMovie; t++) {
>>                                 copyFrames.add(
>>  this.frameLocations.get(((maxSlicesSingleMovie-1)*maxTimesSingleMovie) ) );
>>
>>
>>   this.frameLocations.remove(((maxSlicesSingleMovie-1)*maxTimesSingleMovie)
>>  );
>>                         }
>>                         this.frameLocations.addAll(0, copyFrames);
>>                 } else {
>>                         for (int t= 0; t < maxTimesSingleMovie; t++) {
>>                                 copyFrames.add( this.frameLocations.get(0)
>>  );
>>                                 this.frameLocations.remove(0);
>>                         }
>>                         this.frameLocations.addAll(copyFrames);
>>                 }
>>
>>         }
>>
>>
>>
>>  **Now to the problems I am having (apparently at the level of the JVM??).
>>  Here I try to call the public method MQTVS.adjustSingleMovieZ(int channel,
>>  boolean forward), sending parameters set by the user in the slider of the
>>  PluginFrame.  I have no problems compiling, and get no exceptions reported
>>  in the log window of ImageJ.  But (thanks to help from Wayne), I find a
>>  ClassCastException from the event dispatch thread in the console.  The
>>  confusion comes in the apparent correctness of the type of a variable that I
>>  assign with the ImagePlus.getStack() command, but the wrongness of how the
>>  event dispatch thread deals with the variable when I try to cast it to its
>>  true type (I think). First I show the code from the method in the
>>  PluginFrame that reads the value of sliders and should call
>>  MQTVS.adjustSingleMovieZ(int channel, boolean forward) to change a specific
>  > QTVS's frame position being displayed.  Then below the code, I show the
>>  IJ.log output from several lines in the method, and then the
>>  ClassCastException from the console.
>>
>>  The key method from my PluginFrame MovieAlignFrameMOD:
>  >    public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
>>         ImagePlus imp = WindowManager.getCurrentImage();
>>
>>         ImageStack stack = imp.getStack();
>>         IJ.log(""+stack.getClass().getName() + "1");
>>
>>         ImageWindow win = imp.getWindow();
>>         int zImpPos = imp.getSlice();
>>         int tImpPos = imp.getFrame();
>>         IJ.log("beforetheloop " +  imp+" \n" + imp.getStack()) ;
>>         boolean forward = false;
>>
>>         if (imp==null) return;
>>                 for (int i=0; i< imp.getNChannels(); i++){
>>                         if (e.getSource()==sliceShifter[i]) {
>>                                 int zShiftLive = sliceShifter[i].getValue();
>>                                 int zShiftNet = zShiftLive -
>>  previousShiftZ[i];
>>                                 int zShiftNetAbs = zShiftNet;
>>                                 if (zShiftNet < 0) {
>>                                         zShiftNetAbs = -zShiftNet;
>>                                         forward = true;
>>                                 }
>>                                 previousShiftZ[i] = previousShiftZ[i] +
>>  zShiftNet;
>>
>>                                 for(int j = 0; j < zShiftNetAbs; j++){
>>                                         IJ.log("intheloop j= " + j + " " +
>>  imp+" \n" + imp.getStack()) ;
>>         IJ.log(""+stack.getClass().getName() + "2");
>>
>>                         /** THIS DOES NOT REPORT, SO IT'S CLEAR THAT stack
>>  IS NOT reporting as instanceof MultiQTVirtualStack,
>>                         even though it reports as one using
>>  stack.getClass().getName() **/
>>                                         if (stack instanceof
>>  MultiQTVirtualStack ) IJ.log("MultiQTVirtualStack? Yes!!!!");
>>
>>                         /*** ...But THIS STILL READS OUT AS
>>  MultiQTVirtualStack  ******/
>>
>>         IJ.log(""+stack.getClass().getName() + "3");
>>
>>                         /**** THIS GIVES A "SILENT" ClassCastException ON
>>  THE EVENT DISPATCH THREAD, CAN SEE IN CONSOLE *****/
>>         /* LINE 289 */                  ((MultiQTVirtualStack)
>>  stack).adjustSingleMovieZ(i, forward);
>>
>>                         /***** Once the exception has been thrown, this next
>>  log statement fails to run ***********/
>>
>>         IJ.log(""+stack.getClass().getName() + "4");
>>
>>                                 }
>>
>>                         }
>>                         else if (e.getSource()==frameShifter[i]) {
>>                                 int tShiftLive = frameShifter[i].getValue();
>>                                 int tShiftNet = tShiftLive -
>>  previousShiftT[i];
>>                                 previousShiftT[i] = tShiftNet;
>>                         /****** THE ACTIONS OF THIS IF CONDITION WILL BE
>>  FILLED IN LATER ONCE I FIGURE OUT OTHER PROBLEMS ********/
>>
>>                         }
>>                         notify();
>>                 }
>>         }
>>     }
>>
>>
>>
>>  Here's what is logged by the IJ.log() statements above during a slider
>>  adjustment:
>>
>>  MultiQTVirtualStack1
>>  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
>>
>>
>>  !!Note that I did not leave out the 4th log statement in copying. The CCE
>>  apparently blocks the ability to run the 4th IJ.log statement after line
>>  289.  Also, the instanceof test fails (even before line 289), because I
>>  don't get the "MultiQTVirtualStack? Yes!!!" log printed.
>>
>>
>>  Finally, this is the exception from the event dispatch thread at the
>>  critical line 289:
>>
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748] Exception in
>>  thread "AWT-EventQueue-0" java.lang.ClassCastException: MultiQTVirtualStack
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>  > MovieAlignFrameMOD.adjustmentValueChanged(MovieAlignFrameMOD.java:289)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>  java.awt.Scrollbar.processAdjustmentEvent(Scrollbar.java:1094)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>  > java.awt.Scrollbar.processEvent(Scrollbar.java:1061)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>  java.awt.Component.dispatchEventImpl(Component.java:4068)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>  java.awt.Component.dispatchEvent(Component.java:3903)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>  java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>
>>java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>
>>java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>  java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
>>  4/28/09 10:09:08 AM [0x0-0x4c04c].gov.nih.info.rsb.ImageJ[748]  at
>>  java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
>>
>>
>>
>>  In summary, I seem to have an object called stack returned to me by
>>  ImagePlus.getStack() which both is a MultiQTVirtualStack by some tests and
>>  is NOT a MultiQTVirtualStack by others, and these other criteria are what I
>>  really need to make my PluginFrame work.
>>
>>  Can anyone give me a hint of an explanation of what is going on here?
>>


--
-----------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

dscho
In reply to this post by Bill Mohler
Hi,

On Wed, 29 Apr 2009, Bill Mohler wrote:

> IJ.log(""+stack.getClass().getName() + "2");
>
> /** THIS DOES NOT REPORT, SO IT'S CLEAR THAT stack IS
> NOT reporting as instanceof MultiQTVirtualStack,
> even though it reports as one using
> stack.getClass().getName() **/
> if (stack instanceof
> MultiQTVirtualStack ) IJ.log("MultiQTVirtualStack? Yes!!!!");
>
> /*** ...But THIS STILL READS OUT AS
> MultiQTVirtualStack  ******/
>
> IJ.log(""+stack.getClass().getName() + "3");

Just a hunch, could you compare

stack.getClass().getResource("MultiQTVirtualStack.class")

to

Class.forName("MultiQTVirtualStack").getResource("MultiQTVirtualStack.class")?

(Maybe even MultiQTVirtualStack.class.getResource(...))

I _could_ imagine that there is a class loader problem...

Ciao,
Dscho
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

dscho
In reply to this post by Bill Mohler
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
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
Dscho, thanks for the suggestion, but I seem to be able to figure out
how to work your request for stack.getClass().getClassLoader() (I
can't figure a way to get the class loader for mqtvsClass...)

Here's what prints for stack.getClass().getClassLoader():
ij.io.PluginClassLoader@798928

Can you give me a little more detail on the code if you think I
should be comparing this to another ClassLoader?

Bill

>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
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
In reply to this post by dscho
Dscho, again I'm very new to this stuff.  When I try these
suggestions (from your earlier email), I get the following errors
from Compile and Run:

/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:275:
log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
IJ.log( stack.getClass().getResource("MultiQTVirtualStack.class") );
   ^
/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:277:
log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
IJ.log(Class.forName("MultiQTVirtualStack").getResource("MultiQTVirtualStack.class")
);
   ^
/Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:279:
log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
IJ.log( MultiQTVirtualStack.class.getResource("MultiQTVirtualStack.class") );


????

>Hi,
>
>On Wed, 29 Apr 2009, Bill Mohler wrote:
>
>> IJ.log(""+stack.getClass().getName() + "2");
>>
>> /** THIS DOES NOT REPORT, SO IT'S CLEAR THAT stack IS
>>  NOT reporting as instanceof MultiQTVirtualStack,
>> even though it reports as one using
>>  stack.getClass().getName() **/
>> if (stack instanceof
>>  MultiQTVirtualStack ) IJ.log("MultiQTVirtualStack? Yes!!!!");
>>
>> /*** ...But THIS STILL READS OUT AS
>>  MultiQTVirtualStack  ******/
>>
>> IJ.log(""+stack.getClass().getName() + "3");
>
>Just a hunch, could you compare
>
>stack.getClass().getResource("MultiQTVirtualStack.class")
>
>to
>
>Class.forName("MultiQTVirtualStack").getResource("MultiQTVirtualStack.class")?
>
>(Maybe even MultiQTVirtualStack.class.getResource(...))
>
>I _could_ imagine that there is a class loader problem...
>
>Ciao,
>Dscho
Reply | Threaded
Open this post in threaded view
|

Background gray value/fill?

Frederic V. Hessman
In reply to this post by Bill Mohler
I naively wanted to use the drawing tools to fill in the value of a  
masked region of a 32-bit image: select the value using the picker,  
fill in the area with the fill bucket.

When I tried it, I realized my naivite: the picker is a ColorPicker  
and only sees the look-up-table values, so the REAL values can't be  
picked and filled, at least not for non-color images.

Of course, there are more difficult ways around this problem - create  
a mask, manipulate the mask, apply the manipulated mask - but it seems  
like the straight-forward way of doing it should work.

Before I attempt to modify ColorPicker and Toolbar, I thought I'd ask  
for simpler solutions I haven't thought about.

No, please don't send me a macro - I know one can do it using a dozen  
lines of ImageJ code.   The point is that simple standard things  
shouldn't require an extra macro

Rick



------------------------------------------------------------------------------------------------
Dr. Frederic V. Hessman     [hidden email]
Institut für Astrophysik          Tel.  +49-551-39-5052
Friedrich-Hund-Platz 1         Fax +49-551-39-5043
37077 Goettingen                 Room F04-133
http://www.Astro.physik.Uni-Goettingen.de/~hessman
-------------------------------------------------------------------------------------------------
MONET: a MOnitoring NEtwork of Telescopes
http://monet.Uni-Goettingen.de
-------------------------------------------------------------------------------------------------
Reply | Threaded
Open this post in threaded view
|

Re: Background gray value/fill?

Gluender-3
What about the "Set..." command from the "Process > Math" menu item.
There you can enter a real value with which the current selection is filled.

>I naively wanted to use the drawing tools to
>fill in the value of a masked region of a 32-bit
>image: select the value using the picker, fill
>in the area with the fill bucket.
>
>When I tried it, I realized my naivite: the
>picker is a ColorPicker and only sees the
>look-up-table values, so the REAL values can't
>be picked and filled, at least not for non-color
>images.
>
>Of course, there are more difficult ways around
>this problem - create a mask, manipulate the
>mask, apply the manipulated mask - but it seems
>like the straight-forward way of doing it should
>work.
>
>Before I attempt to modify ColorPicker and
>Toolbar, I thought I'd ask for simpler solutions
>I haven't thought about.
>
>No, please don't send me a macro - I know one
>can do it using a dozen lines of ImageJ code.
>The point is that simple standard things
>shouldn't require an extra macro
>
>Rick
>------------------------------------------------------------------------------------------------
>Dr. Frederic V. Hessman     [hidden email]
>Institut für Astrophysik          Tel.  +49-551-39-5052
>Friedrich-Hund-Platz 1         Fax +49-551-39-5043
>37077 Goettingen                 Room F04-133
>http://www.Astro.physik.Uni-Goettingen.de/~hessman
>-------------------------------------------------------------------------------------------------
>MONET: a MOnitoring NEtwork of Telescopes
>http://monet.Uni-Goettingen.de
>-------------------------------------------------------------------------------------------------

Best
--

                   Herbie

          ------------------------
          <http://www.gluender.de>
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Adrian Daerr-2
In reply to this post by Bill Mohler
> /Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:275:
> log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
> IJ.log( stack.getClass().getResource("MultiQTVirtualStack.class") );

This just means that getResource gives you a Universal Resource Locator
(URL), whereas IJ.log expects a String. To convert any object to a
String representation, just call its toString() method:

IJ.log(
stack.getClass().getResource("MultiQTVirtualStack.class").toString() );

this is implicit in String concatenations, so the following should also
work:
IJ.log(""+ stack.getClass().getResource("MultiQTVirtualStack.class") );

Otherwise, for you problem at hand, maybe there are several .class files
on your disk/in your jars ?

good luck,
Adrian
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

dscho
In reply to this post by Bill Mohler
Hi,

On Wed, 29 Apr 2009, Bill Mohler wrote:

> Dscho, thanks for the suggestion, but I seem to be able to figure out
> how to work your request for stack.getClass().getClassLoader() (I can't
> figure a way to get the class loader for mqtvsClass...)
>
> Here's what prints for stack.getClass().getClassLoader():
> ij.io.PluginClassLoader@798928

Okay, that is what I expected.

For the other class, you might want to try a "Class.forName()" invocation,
or even better, just create an instance right there, and get the active
class loader for that one.

Ciao,
Dscho
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

dscho
In reply to this post by Bill Mohler
Hi,

On Wed, 29 Apr 2009, Bill Mohler wrote:

> Dscho, again I'm very new to this stuff.  When I try these suggestions (from
> your earlier email), I get the following errors from Compile and Run:
>
> /Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:275:
> log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
> IJ.log( stack.getClass().getResource("MultiQTVirtualStack.class") );
>   ^
> /Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:277:
> log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
> IJ.log(Class.forName("MultiQTVirtualStack").getResource("MultiQTVirtualStack.class")
> );
>   ^
> /Applications/ImageJ/plugins/QuickTime_Plugins_MMRD041109/MovieAlignFrameMOD.java:279:
> log(java.lang.String) in ij.IJ cannot be applied to (java.net.URL)
> IJ.log( MultiQTVirtualStack.class.getResource("MultiQTVirtualStack.class") );

The usual way to handle this is to call the .toString() method on the
returned object (which is of type java.net.URL IIRC).

Ciao,
Dscho
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
In reply to this post by dscho
For this line:

IJ.log(" "+ Class.forName("MultiQTVirtualStack").getClass().getClassLoader() );

I get "null" printed.

>Hi,
>
>On Wed, 29 Apr 2009, Bill Mohler wrote:
>
>>  Dscho, thanks for the suggestion, but I seem to be able to figure out
>>  how to work your request for stack.getClass().getClassLoader() (I can't
>>  figure a way to get the class loader for mqtvsClass...)
>>
>>  Here's what prints for stack.getClass().getClassLoader():
>>  ij.io.PluginClassLoader@798928
>
>Okay, that is what I expected.
>
>For the other class, you might want to try a "Class.forName()" invocation,
>or even better, just create an instance right there, and get the active
>class loader for that one.
>
>Ciao,
>Dscho
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

ctrueden
In reply to this post by dscho
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
>
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
In reply to this post by Bill Mohler
Now we're getting somewhere (thanks for the fool-proof code, Curtis):

I put Curtis's 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@c7833c
mqtvs loader = ij.io.PluginClassLoader@c7833c
Loaders equal? true/true
system loader = sun.misc.Launcher$AppClassLoader@a39137
ImageJ loader = ij.io.PluginClassLoader@c7833c

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
mqtvs loader = ij.io.PluginClassLoader@c7833c
Loaders equal? false/false
system loader = sun.misc.Launcher$AppClassLoader@a39137
ImageJ loader = ij.io.PluginClassLoader@c7833c

**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@c7833c
mqtvs loader = ij.io.PluginClassLoader@d1358f
Loaders equal? false/false
system loader = sun.misc.Launcher$AppClassLoader@a39137
ImageJ loader = ij.io.PluginClassLoader@d1358f



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.

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
>>
Reply | Threaded
Open this post in threaded view
|

Re: Strange ClassCastException: A puzzle for Java/ImageJ experts to help me wit?.

Bill Mohler
In reply to this post by Bill Mohler
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
>>
Reply | Threaded
Open this post in threaded view
|

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

Bill Mohler
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.)

pluginFrame controller first, StackOpener second => no exception,
everything's fine.

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
Reply | Threaded
Open this post in threaded view
|

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

Bill Mohler
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