0

While debugging a strange behaviour in Swing I found this tools: CheckThreadViolationRepaintManager edited version by Alex Ruiz. (You must understand what this class does before answering my Question, thanks)

And i fount a thread violation in my code but i dont understand why because I use SwingUtilities.invokeAndWait() everywhere.

Here is the code that cause threadViolation. Only last line cause the bug:

protected void display() {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            asyncDisplay();
        }
    });
}

private void asyncDisplay(){
   System.out.println("is in edt: " + SwingUtilities.isEventDispatchThread());
    this.printedComponent.setVisible(true);
    this.printedComponent.setOpaque(false);
    this.setVisible(true);
}

And the result:

is in edt:  true
exception: java.lang.Exception
java.lang.Exception
at fr.numvision.common.CheckThreadViolationRepaintManager.checkThreadViolations(CheckThreadViolationRepaintManager.java:31)
at fr.numvision.common.CheckThreadViolationRepaintManager.addDirtyRegion(CheckThreadViolationRepaintManager.java:25)
at javax.swing.JComponent.repaint(JComponent.java:4795)
at java.awt.Component.imageUpdate(Component.java:3516)
at javax.swing.JLabel.imageUpdate(JLabel.java:900)
at sun.awt.image.ImageWatched$WeakLink.newInfo(ImageWatched.java:132)
at sun.awt.image.ImageWatched.newInfo(ImageWatched.java:170)
at sun.awt.image.ImageRepresentation.setPixels(ImageRepresentation.java:533)
at sun.awt.image.ImageDecoder.setPixels(ImageDecoder.java:126)
at sun.awt.image.GifImageDecoder.sendPixels(GifImageDecoder.java:447)
at sun.awt.image.GifImageDecoder.parseImage(Native Method)
at sun.awt.image.GifImageDecoder.readImage(GifImageDecoder.java:596)
at sun.awt.image.GifImageDecoder.produceImage(GifImageDecoder.java:212)
at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:269)
at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:205)
at sun.awt.image.ImageFetcher.run(ImageFetcher.java:169)

I really dont understand why this.setVisible(true); cause thread violation (this is a JComponent) while this.printedComponent.setVisible(true); dont.

Thanks,

mKorbel
  • 109,525
  • 20
  • 134
  • 319
zeraDev
  • 381
  • 1
  • 3
  • 16
  • It cause a violation if the thread from which `setVisible` was called wasn't the EDT. The reason the last line may cause it, as it may be the method connects the component to the native peer and starts the repaint process rolling, but that's all guess work and would require a runnable example to be sure – MadProgrammer Feb 27 '15 at 09:49
  • @MadProgrammer please to read OPs question and my comments to answer by Marko Topolnik – mKorbel Feb 27 '15 at 10:15
  • Do you have the `CheckThreadViolationRepaintManager` class and how it's been installed? – MadProgrammer Feb 27 '15 at 10:19
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses. Also, remember, a call to `repaint` doesn't have to occur from within the context of the EDT. Because repaint post's paint events onto the Event Queue, the actual paint operation will occur from within the EDT... – MadProgrammer Feb 27 '15 at 10:36
  • Are you using `ImageIcon` anywhere? – MadProgrammer Feb 27 '15 at 10:46
  • No, but CheckThreadViolationRepaintManager does (that how it detected violation) – zeraDev Feb 27 '15 at 11:20

1 Answers1

1

The code which caused the exception is not synchronous with your this.setVisible(true); line. That line just flags the component as needing a repaint, and the actual repaint event comes in later, afer setVisible() has returned. What seems to be going on is that some other code, somehow causally related to the repainting of your component, submits some GUI code to an external thread.

The details of all this are impossible to derive from the amount of code you have posted.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • [SwingUtilities.invokeAndWait() causing an exception in the case that EDT returns true](http://stackoverflow.com/a/9796519/714968), must be used out of EDT, [the same for paintImmediatelly](http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#paintImmediately%28int,%20int,%20int,%20int%29), both can returns awfull exception (when RepaintManager can lock current JVM == addept only for kills from TaskManager) – mKorbel Feb 27 '15 at 10:12
  • code should be, it must be if (!isEDT) use invokeAndWait() else use invokeLater() :-) – mKorbel Feb 27 '15 at 10:14
  • please to delete this answer here – mKorbel Feb 27 '15 at 10:16
  • I'm still trying to figure out what you're saying :) – Marko Topolnik Feb 27 '15 at 10:17
  • Ok Marko, so "this.setVisible(true)" which is called from EDT cause code somewhere else (but still executed in EDT) to do some GUI operation outside the EDT ?! And the only way to do this is by launching the GUI operation in a new Thread, which i dont do. – zeraDev Feb 27 '15 at 10:23
  • Study the entire stack trace carefully. Code could even be submitted to the other thread directly from the `setVisible` call, but the problem would still reside with what that other thread does. Otherwise you'll need to post the code of your repaint manager to see the exact logic used by it. – Marko Topolnik Feb 27 '15 at 10:29
  • I update the stack so you can see the whole message. My RepaintManager is the CheckThreadViolationRepaintManager from Alex Ruiz. I didn't touch it. And actually there are no other thread running despite standard JVM threads. – zeraDev Feb 27 '15 at 10:37
  • That's highly special-cased code, bound to a certain Java version. However, what is truly puzzling is that it contains a special case exactly matching yours: `imageUpdate`, upon which it just returns. – Marko Topolnik Feb 27 '15 at 10:41
  • checkout : http://stackoverflow.com/questions/7787998/how-to-generate-exceptions-from-repaintmanager he use the same class – zeraDev Feb 27 '15 at 10:50
  • @ Marko Topolnik `I'm still trying to figure out what you're saying` 1. invokeAndWait() is possible to use only when isEventDispatchThread returns false, otherwise returns a.m. (as OPs described) exception, 2. your answer is wrong and hasn't something with, don't touched OPs issue (OP wrote that EDT returns true and then usage of invokeAndWait(be sure that always) returns proper exception), 3. replace invokeLater (in part when EDT returns true) with invokeAndWait (in my linked code) – mKorbel Feb 27 '15 at 14:24
  • @mKorbel Do you mean this exception? [`throw new Error("Cannot call invokeAndWait from the event dispatcher thread");`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/awt/EventQueue.java#1282) Where do you see any evidence of this exception in the stack trace OP posted? – Marko Topolnik Feb 27 '15 at 20:45
  • @zeraDev There are countless variations of that class floating around. I have inspected [this version](https://code.google.com/p/fest/source/browse/trunk/fest/fest-swing/src/main/java/org/fest/swing/edt/CheckThreadViolationRepaintManager.java?spec=svn2323&r=1898) and it has an explicit check for your exact scenario, in which case it *doesn't* throw the exception. The version you have indirectly linked to does not have that special case covered. So I advise using the above version. – Marko Topolnik Feb 27 '15 at 20:54