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? |
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? > |
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 |
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 |
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 |
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 |
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 |
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 ------------------------------------------------------------------------------------------------- |
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> |
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 |
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 |
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 |
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 |
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 > |
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 >> |
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 >> |
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 |
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 |
Free forum by Nabble | Edit this page |