본문 바로가기

공부/컴퓨터

[Java/Tip] Specifc Debugging Tips for Swing - 4.2.1 Incorrect Threading

반응형

자바에서 Swing을 사용할때 별 생각없이 만들다 보면,
EDT가 아닌곳에서 Swing Component에 대한 작업을 많이 하려고 한다.

다른 Thread에서 Swing Component에 대해서 어떠한 작업을 했을때,
dead lock이 일어나기 전에는,
어느곳에서 그런것을 썼는지 일일이 알아 내기가 힘들다.

Print 관련 자료를 찾다가 TroubleshootingGuide for Java를 발견해서
살짝 보았는데 참고해 두고 담에 체크할때 먹으면 좋아 보여서 긁어 놓는다.

TroubleshootingGuide for Java SE 6DesktopTechnologies
http://java.sun.com/javase/6/webnotes/trouble/TSG-Desktop/TSG-Desktop.pdf

4.2.1 IncorrectThreading
Randomexceptions and painting problems are usually the result of incorrect threading usage of Swing. All access to Swing components, unless speciically noted in the javadoc,must be done on the event dispatch thread. This includes anymodels (TableModel, ListModel, and others) that are attached to Swing components.

The best way to check for bad usage of Swing is by way of an instrumented RepaintManager,as illustrated by the following code:

public class CheckThreadViolationRepaintManager extends RepaintManager {

    // it is recommended to pass the complete check
    private boolean completeCheck = true;

    public boolean isCompleteCheck() {
        return completeCheck;
    }

    public void setCompleteCheck(boolean completeCheck) {
        this.completeCheck = completeCheck;
    }

    public synchronized void addInvalidComponent(JComponent component) {
        checkThreadViolations(component);
        super.addInvalidComponent(component);
    }

    public void addDirtyRegion(JComponent component, int x, int y, int w, int h) {
        checkThreadViolations(component);
        super.addDirtyRegion(component, x, y, w, h);
    }

    private void checkThreadViolations(JComponent c) {

        if (!SwingUtilities.isEventDispatchThread() && (completeCheck || c.isShowing())) {

            Exception exception = new Exception();
            boolean repaint = false;
            boolean fromSwing = false;
            StackTraceElement[] stackTrace = exception.getStackTrace();

            for (StackTraceElement st : stackTrace) {
                if (repaint && st.getClassName().startsWith("javax.swing.")) {
                    fromSwing = true;
                }
                if ("repaint".equals(st.getMethodName())) {
                    repaint = true;
                }
            }

            if (repaint && !fromSwing) {
                //no problems here, since repaint() is thread safe
                return;
            }

            exception.printStackTrace();
        }
    }
}
반응형