반응형

Sun Developer Network 공식 블로그 <출처 : http://blog.sdnkorea.com/blog/239 >

대부분의 경우 개발자들은 자바 애플리케이션이 배포된 플랫폼에 딱 맞는 애플리케이션처럼 보이기를 원한다. Mac OS X와 같은 몇몇 플랫폼에서는 적절한 룩앤필이 디폴트값으로 정해지는 반면에 윈도우와 같은 플랫폼은 특정 룩앤필(look and feel)을 설정하기 위해서 다음과 같은 호출이 필요하다.

   UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());

이번 테크팁에서는 탑재된 룩앤필을 플랫폼에 맞도록 결정하게 될 것이다. 새로이 이용 가능한 GTK+ 룩앤필을 추가하고, 라디오 버튼을 클릭해서 룩앤필을 바꿀 수 있는 애플리케이션을 만들게 될 것이다. 마지막으로, 애플리케이션에 사용자의 회사 마케팅 테마에 맞는 룩앤필을 적용하기 위해서 크로스 플랫폼 룩앤필을 사용자 정의하는 방법을 배우도록 하겠다.

인스톨된 룩앤필의 리스트를 생성하자. 정적 메소드 getInstalledLookAndFeels()를 호출하면 LookAndFeelInfo 타입의 객체의 배열을 리턴하게 된다. 인스톨된 LookAndFeels의 이름들을 배열로 얻어내려면 getName()를 이용하고, 구현된 각각의 클래스 이름을 알아내기 위해서는 getClassName()를 사용한다. 인스톨된 LookAndFeels의 이름을 배열로 디스플레이하는 다음 프로그램을 실행해 보자.

   import javax.swing.UIManager;

   public class AvailableLaF {
      public static void main(String[] args) {
        UIManager.LookAndFeelInfo[] installed =
          UIManager.getInstalledLookAndFeels();
        for (int i = 0; i < installed.length; i++) {
          System.out.println(installed[i].getName());
        }
        System.out.println(
          "\nThe current look and feel is "
          + UIManager.getLookAndFeel().getName());
      }
   }

솔라리스 운영환경이나 윈도우 2000에서 실행시켰다면 다음과 같은 출력 값을 보게 된다.

   Metal
   CDE/Motif
   Windows
   
   The current look and feel is Metal

Panther가 실행되는 Mac에서의 출력 값은 다음과 같다.

   Mac OS X
   Metal
   CDE/Motif

   The current look and feel is Mac OS X Aqua

J2SE 1.4.2에서는 GTK+ 2.0에 기반한 크로스 플랫폼 룩앤필도 존재한다. 크로스 플랫폼이 인스톨된 룩앤필의 리스트에 나타나지 않더라도, 이용 가능하다면 이를 인스톨할 수 있다. 크로스 플랫폼 룩앤필을 인스톨하기 위해서는 다음과 같은 메소드가 필요하다.

   private void installGTK() {
      try {
        String GTK =
          "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
        UIManager.setLookAndFeel(GTK);
        UIManager.installLookAndFeel("GTK", GTK);
      } catch (Exception e) {
        System.err.println("Could not install GTK");
      }
    }

GTK는 솔라리스나 Mac OS X와 같은 시스템에서 이용 가능하다. 윈도우에서는 "Could not install GTK" 과 같은 메시지를 보게 될 것이다. GTK를 지원하는 시스템에서 스윙 기반 프로그램을 실행하고자 한다면 커맨드 라인에서 룩앤필을 설정할 수도 있다. 다음은 룩앤필을 설정하는 커맨드 라인이다.

   java -Dswing.defaultlaf=
     com.sun.java.swing.plaf.gtk.GTKLookAndFeel 
     

이하의 프로그램 ChangingLaF는 라디오 버튼을 이용해서 룩앤필을 바꿀 수 있게 해준다. 만약 사용자의 시스템에서 GTK가 이용 가능하다면, 프로그램은 인스톨된 룩앤필의 리스트에 GTK를 추가하게 될 것이다. 그리고 나서 프로그램은 각각의 룩앤필을 위해 라디오 버튼을 생성하게 된다. 프로그램을 실행하고 라디오 버튼을 클릭하면 사용자 인터페이스는 지정한 룩앤필로 바뀌게 된다. 프로그램은 이너클래스의 actionPerformed() 메소드에 대한 응답으로 이를 실행하게 되는 것이다. 다음과 같은 2개의 과정이 수행된다.

   UIManager.setLookAndFeel(getText());
   SwingUtilities.updateComponentTreeUI(
     ChangingLaF.this);

룩앤필은 선택된 라디오 버튼의 텍스트 라벨로 바뀐다. 프로그램은 루트에 주어진 컴포넌트를 이용해서 트리를 새로 그리기 위해 updateComponentTreeUI()를 호출한다. updateComponentTreeUI()JFrame의 인스턴스인 객체를 호출하게 되는데, 이 때 JFrame 은 클래스 이름 뒤에 this가 붙은 형태로 식별된다. 위의 예제에서는, outer 클래스가 ChangingLaF이기 때문에 포함된 인스턴스는 ChangingLaF.this로 식별된다. 변경 가능한 룩앤필 옵션을 갖는 JFrame을 생성하기 위한 전체 ChangingLaF 프로그램을 보자.

   import javax.swing.JFrame;
   import javax.swing.JFileChooser;
   import javax.swing.JPanel;
   import javax.swing.UIManager;
   import javax.swing.JRadioButton;
   import javax.swing.ButtonGroup;
   import javax.swing.SwingUtilities;
   import javax.swing.UnsupportedLookAndFeelException;
   import java.awt.BorderLayout;
   import java.awt.GridLayout;
   import java.awt.event.ActionListener;
   import java.awt.event.ActionEvent;

   public class ChangingLaF extends JFrame {
      private static ButtonGroup group =
                                new ButtonGroup();

      public static void main(String[] args) {
        new ChangingLaF().getContentPane();
      }

      ChangingLaF() {
        JPanel myPanel = new JPanel();
        getContentPane().add(
          myPanel, BorderLayout.SOUTH);
        setLaFButtons(myPanel);
        getContentPane().add(new JFileChooser(),
          BorderLayout.CENTER);
        pack();
        setVisible(true);
      }

      private void setLaFButtons(JPanel choices) {
        installGTK();
        UIManager.LookAndFeelInfo[] laf =
          UIManager.getInstalledLookAndFeels();
        choices.setLayout(new GridLayout(laf.length, 1));
        for (int i = 0; i < laf.length; i++) {
          choices.add(new LaFButton(laf[i]));
        }
      }

      private void installGTK() {
        try {
          String GTK =
            "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
          UIManager.setLookAndFeel(GTK);
          UIManager.installLookAndFeel("GTK", GTK);
        } catch (Exception e) {
          System.err.println("Could not install GTK");
        }
      }

      private class LaFButton extends JRadioButton
        implements ActionListener {
        LaFButton(UIManager.LookAndFeelInfo laf) {
          super(laf.getClassName());
          group.add(this);
          addActionListener(this);
        }

       public void actionPerformed(ActionEvent event) {
         try {
           UIManager.setLookAndFeel(getText());
           SwingUtilities.updateComponentTreeUI(
             ChangingLaF.this);
           // call myFrame.pack() 
           // to resize frame for laf
         } catch (IllegalAccessException e) {
           // insert code to handle this exception
         } catch (UnsupportedLookAndFeelException e) {
           // insert code to handle this exception
         } catch (InstantiationException e) {
           // insert code to handle this exception
         } catch (ClassNotFoundException e) {
           // insert code to handle this exception
         }
       }
     }
   } 

ChangingLaF을 컴파일하고 실행해 보자. 플랫폼에 인스톨된 룩앤필을 쉽게 변경할 수가 있다. J2SE 1.4.2에서는 Windows XP 룩앤필도 적용할 수 있다.

사용자가 룩앤필을 사용자정의하고자 할 때가 종종 있다. 시스템이나 사용자 텍스트의 폰트를 바꾸거나, 컴포넌트를 해당 회사의 마케팅 테마에 맞는 색으로 그려야 하는 경우가 있다. 자, 룩앤필을 사용자 정의하고, 윈도우에서는 GTK가 지원되지 않는 관계로 Metal 테마를 이용하자. 이 예에서 사용하고 있는 DefaultMetalTheme는 J2SE 1.5에서는 더 이상 디폴트값으로 사용되지 않는다.

javax.swing.plaf.metal 패키지내의 클래스들을 살펴보자. MetalLookAndFeel 클래스는 Metal의 자바 구현(Java Implementation)이다. 서브클래스 DefaultMetalTheme는 기초적인 폰트 조절과, 메뉴 아이템, 시스템, 사용자 입력, 윈도우 타이틀 등을 변경하기 위해 사용된다. 이는 또한 3개의 원색과 3개의 2차 색으로 구별되는 6가지 기본 색을 변경하기 위해서도 쓰인다. 다음 CustomTheme프로그램은 DefaultMetalTheme의 서브 클래스를 생성한다. 이 프로그램은 접근 메소드들의 리턴값을 변경함으로써 오버라이드되는 색을 설정하는데, 이는 흰색을 파란색으로, 검은색을 빨강색으로 대체한다. 프로그램은 MetalLookAndFeel 클래스내의 setCurrentTheme() 메소드를 이용해서 이러한 비표준 색 테마를 선택하게 된다.

   import javax.swing.JFrame;
   import javax.swing.JFileChooser;
   import javax.swing.plaf.metal.MetalLookAndFeel;
   import javax.swing.UIManager;
   import javax.swing.UnsupportedLookAndFeelException;
   import javax.swing.plaf.metal.MetalLookAndFeel;
   import javax.swing.plaf.metal.DefaultMetalTheme;
   import javax.swing.plaf.ColorUIResource;
   import java.awt.Color;

   public class CustomTheme {

      public static void main(String[] args)
              throws UnsupportedLookAndFeelException{
        UIManager.setLookAndFeel(
          new MetalLookAndFeel());
        MetalLookAndFeel.setCurrentTheme(
          new CustomLaF());
        JFrame frame = new JFrame("Metal Theme");
        frame.getContentPane().add(new JFileChooser());
        frame.pack();
        frame.setVisible(true);
      }

      static class CustomLaF extends DefaultMetalTheme {
        protected ColorUIResource getPrimary1() {
          return new ColorUIResource(Color.MAGENTA);
        }

        public ColorUIResource getWhite() {
          return new ColorUIResource(Color.BLUE);
        }

        public ColorUIResource getBlack() {
          return new ColorUIResource(Color.RED);
        }

        public ColorUIResource getPrimaryControl() {
          return new ColorUIResource(Color.GREEN);
        }

        protected ColorUIResource getSecondary1() {
          return new ColorUIResource(Color.CYAN);
        }
      }
   }

변경된 테마를 보기 위해서는 Metal 룩앤필이 디폴트로 설정되었는지를 확인해 볼 필요가 있다. (윈도우에서는 필수적으로 확인해 보아야 한다.) 다음과 같이 커맨드 라인에서 애플리케이션을 실행할 수도 있다.

   java -Dswing.defaultlaf=
   javax.swing.plaf.metal.MetalLookAndFeel CustomTheme

스윙 룩앤필에 관한 자세한 정보는 자바 튜토리얼의 How to Set the Look and Feel를 참고하기 바란다.


반응형
Jar 파일에 리소스를 포함하여 배포하였을 경우 그 리소스에 접근하는 방법입니다.

예제코드:
package com.pmguda.resjar;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.sound.sampled.*;
import java.net.*;

public class JarResourceLoading extends JFrame
    implements ActionListener {

    JButton button;
    ImageIcon buttonIcon;
    Clip buhClip;

    public final static String SOUND_PATH = "res/gudaMid.wav";
    public final static String IMAGE_PATH = "res/gudaImage.jpg";

    public JarResourceLoading () {
        super ("Resources from .jar");
        // get image and make button
        URL imageURL = getClass().getClassLoader().getResource (IMAGE_PATH);
        System.out.println ("found image at " + imageURL);
        buttonIcon = new ImageIcon (imageURL);
        button = new JButton ("Click to Buh!", buttonIcon);
        button.setHorizontalTextPosition (SwingConstants.CENTER);
        button.setVerticalTextPosition (SwingConstants.BOTTOM);
        button.addActionListener (this);
        getContentPane().add (button);
        // load sound into Clip
        try {
            URL soundURL = getClass().getClassLoader().getResource (SOUND_PATH);
            System.out.println ("found sound at " + soundURL);
            Line.Info linfo = new Line.Info (Clip.class);
            Line line = AudioSystem.getLine (linfo);
            buhClip = (Clip) line;
            AudioInputStream ais = AudioSystem.getAudioInputStream(soundURL);
            buhClip.open(ais);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void actionPerformed (ActionEvent e) {
        System.out.println ("click!");
        if (buhClip != null) {
            buhClip.setFramePosition (0);
            buhClip.start();
        }
        else
            JOptionPane.showMessageDialog (this,
                                           "Couldn't load sound",
                                           "Error",
                                           JOptionPane.ERROR_MESSAGE);
    }

    public static final void main (String[] args) {
        JFrame frame = new JarResourceLoading();
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}
그림 1.


이클립스에서 jar 파일로 자동 배포 하였습니다. Jar 파일의 내부 구조도 이와 비슷하다.(압축을 풀어보면 알게된다.)

jar 파일안에 있는 이미지의 URL 은  Jar:file:/D:/resource.jar!/res/gudaImage.jpg

위의 코드에 대해 자세히 알아보고자 다른 자료를 찾아보았다.
다른 자료를 조금 인용하기 위해 긁어왔다.. 영문이다. ㅡㅡ;
해석해보면 그리 어렵지 않다. 위의 코드와 조금 다른 부분이 있을것이다. 잘 생각해 보자.


If you want to access a resource (configuration files, images, etc.) then you can certainly put it in a jar file, provided that jar file is in your classpath.

Then to access the resource, you can get a URL to it like this:
            URL url = this.getClass().getResource("/hello.jpg");
or you can get an InputStream to read it like this:
            InputStream is = this.getClass().getResourceAsStream("/app.properties");
Note that these methods will search for the resource in the directory tree relative to the package that "this" is in, so you will generally need the leading "/" to avoid that. But as for executable files in a jar file, forget it, there's no way to execute them from there. You can copy them out to a file and execute them from there, but that's the best you can do.


여기서 짚고 넘어가야 할 것은
패키지: com.pmguda.resjar
클래스: com.pmguda.resjar.JarResourceLoading
1.   getClass().getResource("gudaImage.jpg");
      현재 클래스의 위치에서 리소스를 찾는다
     클래스와 리소스의 위치가 같은 곳에 존재해야 한다.

2.   getClass().getResource("/res/gudaImage.jpg");
     패키지와 동일 루트에서 검색
3.   getClass().getClassLoader.getResource("res/gudaImage.jpg"); 
      패키지와 동일 루트에서의 상대 위치를 나타낸다.

java.lang.Class.getResource(String name)



번역이 완전하지가 않아 이해하기 어려울듯 하다.

java.lang.Class.getResource(String name)에서
name 가 "/gudaImage.jpg" 일 경우 절대 경로명(/gudaImage.jpg)으로 사용되고
"gudaImage.jpg" 일 경우 현 클래스의 위치에서 시작하는 상대경로가 되겠지요 이를
절대경로로
나타내면 (/com/pmguda/resjar/gudaImage.jpg)

java.lang.ClassLoader.getResource(String name)



1. getClass().getResource("/res/gudaImage.jpg"); 
2. getClass().getClassLoader.getResource("res/gudaImage.jpg"); 
동일한 URL을 리턴한다. 2번예시에서 앞에 "/" 을 넣어 시작하지 말도록 하자.
2번은 항상 상대경로만 인식하여 사용된다고 명심하시길..
ex)getClass().getClassLoader.getResource("/res/gudaImage.jpg");  

조금더 알아보고자 한다면 ClassLoader 에 대해 알아보는 것도 좋을듯 하다.
http://www.ibm.com/developerworks/kr/series/j-dclp.html?ca=dnn-krt-20071226

반응형
스윙에서는 다양한 종류에 룩앤필을 적용할수가 있다.

일단 java api에서 UIManager 에 대해 잠깐 조사해 보자.

Look & Feel 의 지정

Look & Feel 의 지정 방법은 2 서로 통과합니다. 1 개(살)은 Look & Feel 의 클래스의 완전 지정의 이름을 지정하는 방법, 이제(벌써) 1 개(살)은 LookAndFeel 의 인스턴스를 작성해,setLookAndFeel 에 건네주는 방법입니다. 다음에, 시스템의 Look & Feel 를 Look & Feel 로서 설정하는 예를 나타냅니다.
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 
다음에, 클래스명을 지정해 Look & Feel 를 설정하는 예를 나타냅니다.
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
 
Look & Feel 를 변경하면(자) 반드시, 모든 JComponents 상에서 updateUI 를 호출합니다. SwingUtilities.updateComponentTreeUI(java.awt.Component) 메소드를 사용하면(자), 포함 관계의 계층에 updateUI 를 간단하게 적용할 수 있습니다. 자세한 것은, 이 메소드를 참조해 주세요. Look & Feel 의 변경 후,updateUI 를 호출하지 않았던 경우의 정확한 동작은 지정되고 있지 않습니다. 예기치 않은 예외, 페인트의 문제, 또는 그 이상으로 곤란한 사태가 발생할 가능성이 높습니다.
-----------------  API 참조  --------------------------
try{
UIManager.setLookAndFeel(룩앤필 클래스이름);
}catch(Exception e){}

룩앤필은 익셉션을 발생시키기 때문에 try catch 문을 이용해 처리해 주면된다.

자바프로그램이 실행되는 시스템의 룩앤필을 적용하고자 할때는

룩앤필 클래스 이름: UIManager.getSystemLookAndFeelClassName()

ex)

try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exception e){}

이렇게 해주면 되고 기타 다른 룩앤필을 적용하는 방법도 있다.

http://www.jgoodies.com/downloads/libraries.html 이 사이트에 라이브러리를 적용해
룩앤필을 적용하는것도 자기가 원하는 디자인을 표현하는 것도 좋을것이다.
반응형
Wikipedia에 따르면 스플래시 스크린은 프로그램이나 운영체제가 로딩되는 동안 표시되는 이미지를 가리키는 컴퓨터 용어로서, 사용자에게 프로그램이 초기화되고 있다는 것을 시각적으로 보여주는 역할을 한다. Java SE 6(코드명 Mustang)가 출시되기 전에는 메인 메소드를 시작할 때 창을 만들고 그 속에 이미지를 배치하여 스플래시 스크린의 동작을 보여주는 것이 고작이었다. 이것도 나름대로 유용했지만, 창이 표시되기 전에 Java 런타임이 완전히 초기화될 필요가 있었다. 한편, 이 초기화 과정에는 AWT와 보통 Swing이 포함되어 초기 그래픽 디스플레이를 지연시키는 원인이 되었다. Mustang의 경우에는, 새로운 명령어 라인 옵션으로 이 기능을 훨씬 쉽게 만들어줄 뿐 아니라 사용자에게 이미지를 더 빠르게, 즉 Java 런타임이 시작되기도 전에 디스플레이를 가능하게 해준다. 이 기능이 최종적으로 포함되려면 JCP의 승인을 받아야 한다.

명령어 라인 옵션

명령어 라인으로 프로그램을 실행하면 -splash 명령어 라인 스위치를 통해 스플래시 스크린을 생성할 수 있다. 이 기능은 스크립트, 배치 파일, 바탕화면 바로가기 등을 이용해서 프로그램을 실행할 때 특히 유용하며, 명령어 라인 스위치 뒤에는 다음과 같은 이미지 이름이 온다.
   java -splash:Hello.png HelloWorld
-splash와 이미지 이름 사이에는 콜론이 들어간다. 이렇게 하면 런타임 환경이 완전히 초기화되기 전에 이미지가 즉시 디스플레이된다(화면의 중앙에 디스플레이됨). 스플래시 스크린 이미지에는 GIF, PNG, JPEG 등의 포맷이 사용될 수 있으며, 통상적인 Image 클래스와 마찬가지로 스플래시 스크린 이미지는 애니메이션, 투명(transparency), 반투명(translucency. Microsoft Windows 2000 또는 XP에서만 지원) 등의 효과를 지원한다. 애플리케이션이 첫 번째 창을 생성하면 스플래시 스크린은 사라진다.

JAR 파일 Manifest

일반적으로 대부분의 사용자는 명령어 라인 엔트리에 -splash를 삽입하기를 원치 않는다. 따라서, 보다 효과적으로 스플래시 스크린을 디스플레이하는 방법은 애플리케이션을 위한 manifest 파일을 생성한 다음 애플리케이션에 JAR 파일 내의 manifest와 이미지를 결합하는 것이다. 사용자가 JAR 파일로부터 애플리케이션을 론치할 때 스플래시 스크린이 표시되는데, 이 경우에는 사용자가 명령어 라인 옵션을 지정하지 않아도 된다.

manifest 파일 옵션은 SplashScreen-Image로 명명되고, 옵션 뒤에는 이미지 파일명이 온다. 파일이 JAR 파일의 톱 레벨에 있지 않을 경우에는 파일명의 전체 경로를 지정할 필요가 있다.

다음은 이 새로운 스플래시 스크린 기능들을 보여주는 간단한 예제이다 . 먼저, 다음 프로그램을 작성하도록 한다.
   import javax.swing.*;
   import java.awt.*;
   
   public class HelloSplash {
     public static void main(String args[]) {
       Runnable runner = new Runnable() {
         public void run() {
           try {
               Thread.sleep(1500);
           } catch (InterruptedException e) {
           }
           JFrame frame = new JFrame("Splash Me");
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           JLabel label = new JLabel(
                "Hello, Splash", JLabel.CENTER);
           frame.add(label, BorderLayout.CENTER);
           frame.setSize(300, 95);
           frame.setVisible(true);
        }
       };
       EventQueue.invokeLater(runner);
     }
    } 
이어서 프로그램을 컴파일한다.
    javac HelloSplash.java
그런 다음 명령어 라인 -splash를 시험해본다. 작업을 단순화시키기 위해, 프로그램과 동일한 디렉터리에 있는 스플래시 스크린 이미지를 사용한다.
   java -splash:MyImage.png HelloSplash
MyImage가 즉시 화면 중앙에 배치되고, 이어서 Java 런타임 환경이 초기화되고 나면 애플리케이션 화면이 표시되는 것을 알 수 있다.

My Image

Hello Splash

이제 JAR 파일 방식을 시험해 보기로 하자. 먼저 manifest를 위한 manifest.mf 파일을 생성한다. 파일의 내용은 다음과 같은 형태이어야 한다.
   Manifest-Version: 1.0
   Main-Class: HelloSplash
   SplashScreen-Image: MyImage.png
이어서 JAR 파일을 패키지한다.
   jar -mcvf manifest.mf Splash.jar HelloSplash*.class MyImage.png
그런 다음 -splash 명령어 라인 옵션을 지정하지 않고 JAR를 실행한다.
   java -jar Splash.jar
이전과 마찬가지로 스플래시 스크린에 이어서 애플리케이션 화면이 표시되어야 한다.

여러분의 JAR 파일이 manifest에 지정된 스플래시 스크린 이미지를 가지고 있고, 사용자가 명령어 라인에서 스플래시 이미지를 지정하는 경우에는 명령어 라인 이미지에 우선권이 주어지고 대신 표시된다.

고급 기능

대개의 경우에는 명령어 라인 -splash 및 manifest SplashScreen-Image 옵션으로 충분하지만, Mustang에는 더 많은 스플래시 스크린 기능이 들어 있다. java.awt 패키지는 단순히 스플래시 스크린 이미지를 보여주는 것 이상의 진보된 기능을 위한 SplashScreen 클래스를 제공한다.

-splash 명령어 라인 옵션이나 manifest의 SplashScreen-Image 옵션으로 이미지가 생성된 경우에는 SplashScreen 클래스의 getSplashScreen() 메소드가 생성된 화면을 반환한다. 이미지가 생성되지 않았다면 getSplashScreen()이 null을 반환한다.

다른 SplashScreen 메소드를 이용해서 스플래시 스크린과 관련된 다양한 사실을 알아낼 수 있다.
  • getBounds()는 스플래시 스크린 직사각형의 바운드를 반환한다.
  • getImageURL()은 스플래시 스크린 이미지의 URL을 반환한다.
  • getSize()는 스플래시 스크린 창의 크기를 반환한다.
  • isVisible()은 스플래시 스크린이 가시적인지 여부를 알려준다.
스플래시 스크린이 로드된 후에 이미지를 변경할 수 있지만, 이는 애플리케이션이 시작되기 전까지만 가능하다. 여기에는 두 가지 방법이 사용된다. setImageURL() 메소드는 디스플레이할 새 이미지에 대한 URL을 제공할 수 있게 해주고, 더 일반적인 두 번째 방법은 getGraphics() 메소드를 호출하여 창의 그래픽 컨텍스트(java.awt.Graphics)를 얻는 것이다. 그런 다음 통상적인 그래픽과 Java 2D API를 통해 이미지를 업데이트하는데, 그 이유는 이것이 단순한 java.awt.Graphics가 아니라 Graphics2D의 인스턴스이기 때문이다. 그래픽 컨텍스트에 드로우(draw)한 후 SplashScreenupdate() 메소드를 호출하여 업데이트된 이미지를 드로우한다.

다음은 스플래시 스크린에 표시되는 일련의 색상을 순환하는 후반의 동작을 보여주는 예제이다. 이것이 프로그레스 바, 또는 애플리케이션 초기화의 진행 상태를 나타내는 다른 상태 데이터를 디스플레이하는 것을 상상해보라.
   import javax.swing.*;
   import java.awt.*;
   import java.awt.geom.*;
   import java.util.*;

   public class ExtendedSplash {
     public static void main(String args[]) {
       Runnable runner = new Runnable() {
         public void run() {
           Random random = new Random();
           SplashScreen splash = SplashScreen.getSplashScreen();
           Graphics2D g = (Graphics2D)splash.getGraphics();
           Dimension dim = splash.getSize();
           Color colors[] = {Color.RED, Color.ORANGE, 
             Color.YELLOW, Color.GREEN, Color.BLUE, 
             Color.MAGENTA};
           for (int i=0; i<100; i++) {
             g.setColor(colors[i % colors.length]);
             g.fillRect(50, 50, dim.width-100, dim.height-100);
             splash.update();
             try {
               Thread.sleep(250);
             } catch (InterruptedException ignored) {
             }
           }
           JFrame frame = new JFrame("Splash Me2");
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           JLabel label = 
             new JLabel("Hello, Splash", JLabel.CENTER);
           frame.add(label, BorderLayout.CENTER);
           frame.setSize(300, 95);
           frame.setVisible(true);
         }
       };
       EventQueue.invokeLater(runner);
     }
   }
color Splash

스플래시 스크린 이미지 위에서 어떻게 드로잉이 이루어지는지 주목할 것.

예제는 색상 순환이 완료된 후의 프레임을 보여주는데, 이는 시동 과정의 전형적인 양상으로, 초기화가 완료된 후 프레임이 표시되면서 스플래시 스크린을 가리게 된다.

마지막으로 언급할 SplashScreen 옵션의 경우 close() 메소드가 사용되는데, 창을 닫고 관련된 리소스를 해제하고자 할 경우에 이 메소드를 호출할 수 있다. 첫 번째 창이 가시적으로 되면 이 메소드가 자동으로 호출되기 때문에 굳이 호출할 필요는 없다.

스플래시 스크린을 이용하는 방법에 관한 자세한 내용은 테크니컬 아티클 “Mustang의 새로운 스플래시 스크린 기능(New Splash-Screen Functionality in Mustang)”을 참조하기 바란다. 아울러, SplashScreen 클래스를 위한 javadoc을 함께 참조할 것.

<출처: http://blog.sdnkorea.com/blog/171 >

참고자료로 구글링을 하면서  스플래시 스크린 자료를 찾았다.
http://www.jcreator.co.kr/tag/Splash%20Screen 
<이전 스플래시 스크린 자료 -window 클래스를 이용 >
http://www.devdaily.com/java/edu/SplashScreen
http://www.javapractices.com/topic/TopicAction.do?Id=149
반응형

Install TPTP 4.5.2 using the Ganymede update site

Ganymede is the Eclipse simultaneous release in 2008. It includes TPTP 4.5.2 and all of its dependencies. The Ganymede update site provides an easy way to install TPTP and its dependencies. Step-by-Step illustration is also available on the TPTP wiki page.

  1. Install Eclipse SDK version 3.4
  2. From the menu, select Help > Software Updates.
  3. Select the "Available Software" tab in the "Software Updates and Add-ons" dialog box.
  4. Expand the "Ganymede" entry.
  5. Expand the "Testing and Performance" entry and choose the options to install. Equinox p2 will automatically install the required dependencies.
  6. Click Install, and follow the instructions to complete the installation. Restart Eclipse when prompted.

 

반응형

Java 6 update10 에서 윈도우 Frame 투명화가 가능해졌네요.

이리저리 찾아보고 있었는데 자료를 찾았습니다. ㅎㅎ

원래 투명하게 보이는걸 좋아해서.. 내가 만든 플램도 넣고 싶었는데..

Java 라서 안되는구나.. 했는데 드디어 지원한다니 ㅋㅋ

영문 자료입니다.. 즐프 하시길..^^

How to Create Translucent and Shaped Windows

http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/

The article describes a feature that allows creating applications with translucent and shaped windows.

Contents
 
Introduction
Feature Overview
 
Translucent Windows
Shaped Windows
API Overview
Using the Feature
 
Determining the Support for a Desired Effect
Making a Window Translucent
 
Setting the Opacity Level of a Window
Enabling Per-Pixel Translucency
Setting the Opacity Level of a Window
Translucent and Shaped Windows Demo
Summary
 

JavaFX Script is a capable new language that offers a set of APIs for creating RIAs. It also provides you with access to the rich features of the the standard Java language. One of the major features introduced in the Java SE 6u10 release is the ability to create translucent and shaped windows. This includes:

  • making application windows translucent (tuning the general opacity of the window and using a per-pixel translucency effect)
  • setting shapes on application windows

This feature is available for objects of the java.awt.Window class and its descendants, for example javax.swing.JFrame, javax.swing.JFDialog, java.awt.Frame.

Translucent Windows
The translucent windows capability tunes the appearance of application windows using two different effects - simple translucency and per-pixel translucency. First, we will give an overview of the simple translucency effect. The simple translucency effect is used to make a window evenly translucent. When simple translucency is applied to a window, all the pixels of the window are assigned an alpha value which determines the level of opacity from the available range. The smaller the value, the more transparent the given window becomes. The minimum opacity level provides a completely transparent window, while the maximum opacity level represents a completely non-transparent (i.e. opaque) window. The following images demonstrate the use of the effect in four cases:

Dialog window without the effect applied Evenly translucent dialog window with opacity level 85%
Figure 1. Dialog window without the effect applied
Figure 2. Evenly translucent dialog window with opacity level 85%
Evenly translucent dialog window with opacity level 45% Evenly translucent dialog window with opacity level 25%
Figure 3. Evenly translucent dialog window with opacity level 45%
Figure 4. Evenly translucent dialog window with opacity level 25%
 

The screenshots are taken from the Translucent and Shaped Windows Demo. For details, see the Demo section. For more information about the effect and its use, see Setting the Opacity Level of a Window.

Another feature new to this release is the per-pixel translucency effect. Like simple translucency, per-pixel translucency can be used to make a window evenly translucent, though it is not recommended for performance reasons. However, it also enables you to control the opacity level of each individual pixel independently in order to make the window non-uniformly translucent or transparent. A good example of the use of the per-pixel effect is a gradient effect when the opacity "strength" of the window background increases from its top to the bottom. The following images show the per-pixel translucency effect in action for two cases:

The dialog window is evenly translucent using per-pixel alpha with 50% level
A gradient effect from fully translucent (upper left corner) to fully opaque
Figure 5. The dialog window is evenly translucent using per-pixel alpha with 50% level (note that the button remains opaque)
Figure 6. A gradient effect from fully translucent (upper left corner) to fully opaque (lower right corner) has been applied to the dialog window (note that the button remains opaque)
 

Note that when the per-pixel translucency effect is applied to make a window area transparent, the area may or may not remain clickable - this is a platform dependent behavior. For more information about the effect and its use, see Enabling Per-Pixel Translucency.

To sum up, the simple translucency effect is used to make a window evenly translucent or transparent, and the per-pixel translucency effect enables you to make a window evenly or non-uniformly translucent or transparent. Both the simple translucency and the per-pixel translucency can be used to make a window evenly translucent or transparent. However, when applied, the simple translucency effect consumes fewer system resources.

Shaped Windows
The other feature introduced in release 6u10 is the window shaping effect. Using shaping you can set any shape to an undecorated window. When the effect is applied, the desired area of a window becomes transparent. Thus, the combination of transparent and non-transparent pixels form the shape of a given window. The next images demonstrate window shaping in two cases:

Oval dialog window
Rounded rectangle dialog window
Figure 7. Oval dialog window
Figure 8. Rounded rectangle dialog window
 

Note that transparent areas of the window become unclickable. For more information about the effect and its use, see Setting the Shape of a Window.

These effects can be applied in combination. For example, you can create an oval shaped translucent window or a rounded rectangle window with the gradient effect applied:

Oval evenly translucent dialog window
Rounded rectangle dialog window with the gradient effect applied
Figure 9. Oval evenly translucent dialog window
Figure 10. Rounded rectangle dialog window with the gradient effect applied
 

Note that the effects may not be supported by the underlying platform (either because of hardware or software limitations or both). Therefore, before applying the effect, make sure that the platform supports it. For more details on system support, see Determining the Support for a Desired Effect.

The translucent and shaped windows feature is available through the new com.sun.awt.AWTUtilities class.

Note: the com.sun.awt.AWTUtilities class is not part of an officially supported API and appears as an implementation detail. The API is only meant for limited use outside of the core platform. It may change drastically between update releases, and it may even be removed or be moved in some other packages or classes. The class should be used via Java Reflection. Supported and public API will appear in the next major JDK release.

Method (* all the methods in the table are public and static)
Purpose
enum Translucency
Represents the kinds of translucency supported by the underlying system
boolean isTranslucencySupported(Translucency translucencyKind)
Returns if the given level of translucency is supported by the underlying system
void setWindowOpacity(Window window, float opacity)
Sets the opacity of a window
float getWindowOpacity(Window window)
Returns the opacity of a window
Shape getWindowShape(Window window)
Returns the shape of a window
void setWindowShape(Window window, Shape shape)
Sets the shape of a window
void setWindowOpaque(Window window, boolean isOpaque)
Enables the per-pixel translucency for a window
boolean isWindowOpaque(Window window)
Returns whether the window is opaque or translucent
boolean isTranslucencyCapable(GraphicsConfiguration gc)
Verifies whether a given graphics configuration supports the per-pixel translucency
 

Determining the Support for a Desired Effect
As already mentioned, the underlying system may not support the desired effect. That is why it is necessary to perform system support validation. The simple translucency and shaping effects require only general validation which indicates whether the system supports the effect in general.

To determine whether your system supports the effect, use the AWTUtilities.isTranslucencySupported() method passing a corresponding constant value as an argument. The constants PERPIXEL_TRANSPARENT, TRANSLUCENT, PERPIXEL_TRANSLUCENT represent shaping, simple translucency, and per-pixel translucency respectively. The next example shows how to determine whether your system supports simple translucency:

if (AWTUtilities.isTranslucencySupported(AWTUtilities.Translucency.TRANSLUCENT) {
      //perform translucency operations here
}
 

The per-pixel translucency also requires a window be created using a compatible graphics configuration. To check whether the given graphics configuration supports the per-pixel translucency effect use the isTranslucencyCapable() method. The following example shows how to determine whether the default graphics configuration supports per-pixel translucency:

if ((AWTUtilities.isTranslucencySupported(AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT)) &&
      (AWTUtilities.isTranslucencyCapable(defaultTranslucencyCapableGC))) {
      //perform translucency operations here
}
 

In case the default graphics configuration is not per-pixel translucency capable, you can go through all available graphics configurations and find one capable of translucency. Use the following code snippet:

GraphicsEnvironment env =
           GraphicsEnvironment.getLocalGraphicsEnvironment();
       GraphicsDevice[] devices = env.getScreenDevices();

     for (int i = 0; i < devices.length && translucencyCapableGC == null; i++) {          GraphicsConfiguration[] configs = devices[i].getConfigurations();          for (int j = 0; j < configs.length && translucencyCapableGC == null; j++) {              if (AWTUtilities.isTranslucencyCapable(configs[j])) {                  translucencyCapableGC = configs[j];              }          }      }

 

Once it has been determined that the system supports the desired effect, you can proceed to apply it to your top-level windows.

Making a Window Translucent
Setting the Opacity Level of a Window
The general opacity level of the application window is controlled by the the setWindowOpacity method. This method takes window and opacity variables as arguments. The window argument defines the window to apply the effect to. This argument must be an instance of the java.awt.Window class or its descendant, such as javax.swing.JFrame. The opacity argument is responsible for the level of opacity of the window. The lower its value, the more transparent the window becomes. The range of allowed values is [0f ; 1f]. If you set the value to 0f, the window becomes completely transparent (i.e. invisible). If the value is set to 1f, then the window becomes completely opaque (which is equal to a case when the effect is not applied at all). If the opacity level value is out of the range, it throws an IllegalArgumentException. Note that the effect can not be applied to full-screen windows. If you are in full screen windows mode and the opacity value is lower than 1f, you will get an IllegalArgumentException.

The following code snippet shows how to set the opacity level for your window. To make the window translucent, the example uses the setWindowOpacity method via Java Reflection, passing window and 0.75f as arguments. Window is an instance of the JFrame class, 0.75f is the value of the translucency.

Note that all the examples from this article that use the AWTUtilities class should be implemented via Java Reflection API.

try {
   Class<?> awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities");
   Method mSetWindowOpacity = awtUtilitiesClass.getMethod("setWindowOpacity", Window.class, float.class);
   mSetWindowOpacity.invoke(null, window, Float.valueOf(0.75f));
} catch (NoSuchMethodException ex) {
   ex.printStackTrace();
} catch (SecurityException ex) {
   ex.printStackTrace();
} catch (ClassNotFoundException ex) {
   ex.printStackTrace();
} catch (IllegalAccessException ex) {
   ex.printStackTrace();
} catch (IllegalArgumentException ex) {
   ex.printStackTrace();
} catch (InvocationTargetException ex) {
   ex.printStackTrace();
}
 

When applied, the method makes the frame translucent with a 75% level of opacity.

To get the current opacity of a window, use the getWindowOpacity method passing a window object as its argument. If the opacity level has not yet been set, this method returns 1.0f. In case the method returns 0f, the window is completely transparent. The next code snippet shows how to get the current level of opacity of a window:

float opacity = AWTUtilities.getWindowOpacity(frame);
 

Enabling Per-Pixel Translucency
The setWindowOpaque method is used to enable per-pixel alpha support for the given window. The method takes the window and isOpaque variables as arguments. The window argument defines the window you apply the effect to. Note that the argument must represent a window created using an effect compatible graphics configuration. For more information on graphics configurations, see Determining the Support for a Desired Effect. Also note that the window must not be in full-screen mode when making it non-opaque, or an IllegalArgumentException is thrown.

The isOpaque parameter defines whether the window must be opaque (true), or translucent (false). Once the window becomes non-opaque (the isOpaque is set to false), the drawing sub-system starts to respect the alpha value of each individual pixel. If a pixel gets painted with an alpha color component equal to zero, it becomes visually transparent; if the alpha of the pixel is equal to 255, the pixel is fully opaque. Interim values of the alpha color component make the pixel semi-transparent (i.e. translucent). The following code snippet shows how to enable the per-pixel alpha support for your window.

AWTUtilities.setWindowOpaque(frame, false);
 

If invoking the getWarningString on the window object returns a non-null String, this method will not affect the opacity of the window.

The following code snippet shows how to achieve the gradient effect. It is done by defining the parameters of the JPanel component using the GradientPaint method:

jPanel1 = new javax.swing.JPanel() {
      protected void paintComponent(Graphics g) {
          if (g instanceof Graphics2D) {
              final int R = 240;
              final int G = 240;
              final int B = 240; 

            Paint p =             new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0),                 getWidth(), getHeight(), new Color(R, G, B, 255), true);             Graphics2D g2d = (Graphics2D)g;             g2d.setPaint(p);             g2d.fillRect(0, 0, getWidth(), getHeight());      } else {     super.paintComponent(g);      }    }  }

 

Then the component should be placed on the frame:

frame.add(jPanel1);
 

Setting the Shape of a Window
To apply a shape to a window use the setWindowShape method. The method uses the window argument to define the window you want to set the shape to. Additionally, it uses the shape argument to define the desired shape. The shape can be any instance of the java.awt.Shape interface, for example, Ellipse2D.Float or RoundRectangle2D.Float. The next code snippet shows how to set an oval shape on your window. In the example, the fd argument represents the JFrame window, Ellipse2D.Float creates a new instance of an Ellipse2D object that defines the shape of the window:

fd.addComponentListener(new ComponentAdapter() {
     @Override
     public void componentResized(ComponentEvent evt) {
       Shape shape = null;
       shape = new Ellipse2D.Float(0, 0, fd.getWidth(), fd.getHeight());
       AWTUtilities.setWindowShape(fd, shape);
     }
});
 

It is recommended to set the shape using the componentResized() method as this enables precise control of the shape according to the current size of the window.

When setting the shape on your window, note that the effect supports only undecorated windows. If your window is decorated and you apply the effect, you will get the original shape of the window without the effect applied to it. If the window has been created by untrusted code (i.e. the window has a non-null warning string returned by getWarningString()), the method returns without affecting the shape of the window. Also note that the window must not be in the full-screen mode when setting a non-null shape. Otherwise, an IllegalArgumentException is thrown.

To get the current value of the shape of a window, use the getWindowShape method passing a window as an argument. The getWindowShape method returns an object that implements the shape interface and represents the shape previously set . If no shape has been set yet, or the shape has been reset to null, this method returns null. In other words, the default rectangular shape is displayed when the null argument is passed. The following code demonstrates how to get the current shape of the window:

Shape currentShape = AWTUtilities.getWindowShape(frame);
 

You can see the translucency and shape features in action by running the "TranslucencyShapeDemo" example. Click the Launch button to run Demo using Java Web Start. Note that in order to start the demo you must have JDK 6u10 or later installed and properly configured on your machine. You can download release 6u10 at the java.sun.com download page.

The application enables you to choose a desired effect or a combination of effects and apply it to an undecorated dialog window. The application interface contains the following elements: a slidebar to set the level of constant alpha for the simple translucency effect from the range [0% ; 100%], three radio buttons to set the shape of a window - rectangular, with rounded corners, or oval, a check box to enable or disable the per-pixel gradient effect, Paint Gradient check box to switch the per-pixel gradient effect on and off, Display/Hide the frame and Close the Application buttons. Once the settings are defined, click the Display the frame button to display the dialog window with the desired effect applied. Note that you can also change the effect spontaneously. To do so, choose an effect type when the window is displayed, the window will automatically switch its view. The dialog window itself contains the Reshape Me button. When clicked, the window randomly changes its size and location on the desktop. To hide the dialog window, click Hide the frame, to close the application, click Close the Application button.

Launches the TranslucentShapes application

You can find the entire code for this program in ControlFrame.java, FancyFrame.java, Main.java, and AWTUtilitiesWrapper.java, all of which are packed in the TranslucentShapes NetBeans project. Note that the application uses the Java Reflection API. The Reflection mechanism is implemented through the AWTUtilitiesWrapper class. You can download the TransclucentShapes NetBeans project as a zip file.

This article provides a description of the translucent and shaped windows feature. It includes an overview, discusses the feature API, and offers practical examples. The demo attached to the article shows the use of each featured effect individually as well as the use of the effects in combination.

반응형

개발 도구

  1. Eclipse : http://www.eclipse.org/
  2. Netbean : http://www.netbeans.org/community/releases/60/index.html
  3. Firebug : http://www.getfirebug.com/

소스코드 관리

  1. CVS : http://www.cvshome.org
  2. Subversion : http://subversion.tigris.org
  3. MS Visual SourceSafe
  4. BitKeeper : http://www.bitkeeper.com
  5. ClearCase : http://www-306.ibm.com/software/awdtools/clearcase/

빌드 스크립트 도구

  1. make : http://source.redhat.com/cygwin
  2. Automake : http://www.gnu.org/software/automake
  3. Ant : http://ant.apache.org
  4. NAnt : http://nant.sourceforge.net
  5. Groovy : http://groovy.codehaus.org
  6. Rake : http://rake.rubyforge.org/  
  7. SCons : http://www.scons.org/

빌드 시스템

  1. Mavenhttp://maven.apache.org 
  2. Maven2 : http://maven.apache.org/maven2/index.html

CI 도구 (Continuous integration )

  1. CruiseControl : http://cruisecontrol.sourceforge.net
  2. CruiseControl .NET : http://sourceforge.net/projects/ccnet
  3. DamageControl : http://damagecontrol.codehaus.org
  4. AntHill : http://www.urbancode.com/projects/anthill
  5. Continuum : http://maven.apache.org/continuum
  6. LuntBuild : http://luntbuild.javaforge.com/  
  7. Buildix : http://buildix.thoughtworks.com/  
  8. Hudson : https://hudson.dev.java.net/  (직관적이고 사용법이 쉬움)

이슈 추적 도구

  1. Bugzilla : http://www.bugzilla.org
  2. JIRA : http://www.atlassian.com/software/jira/default.jsp
  3. FogBugz : http://www.fogcreek.com/FogBugz
  4. PR-Tracker : http://www.prtracker.com  
  5. Trac : http://trac.edgewall.org/

테스트 프레임워크

  1. JUnit : http://www.junit.org
  2. NUnit : http://www.nunit.org
  3. xUnit.NET : http://www.codeplex.com/xunit
  4. MbUnit : http://www.mbunit.org
  5. HTMLUnit : http://htmlunit.sourceforge.net
  6. HTTPUnit : http://httpunit.sourceforge.net
  7. JWebUnit : http://jwebunit.sourceforge.net
  8. Cobertura : http://cobertura.sourceforge.net
  9. Clover : http://www.cenqua.com/clover  
  10. Cactus : http://jakarta.apache.org/cactus/
  11. Emma : http://emma.sourceforge.net/
  12. Fit : http://fit.c2.com
  13. Fitness : http://fitnesse.org  
  14. Watir : http://wtr.rubyforge.org
  15. Systir : http://atomicobject.com/systir.page
  16. AUT : http://aut.tigris.org/
  17. UnitTest++ : http://unittest-cpp.sourceforge.net/  
  18. TestNG : http://testng.org/doc/  
  19. CppUnit : http://sourceforge.net/projects/cppunit  
  20. CppUnit2 : http://cppunit.sourceforge.net/cppunit-wiki/CppUnit2  
  21. Selenium : http://www.openqa.org/
  22. Agitar : http://www.agitar.com/  
  23. JTest : http://www.parasoft.com/jsp/home.jsp  
  24. PushToSoft : http://www.pushtotest.com/  
  25. Eclemma : http://www.eclemma.org/

프로젝트 관리

  1. OpenProj : http://openproj.org/openproj 
  2. dotproject : http://www.dotproject.net/
  3. Mantis : http://www.mantisbt.org/

커뮤니케이션 도구, 위키

  1. MoinMoin : http://moinmoin.wikiwikiweb.de/
  2. Confluence : http://www.atlassian.com/software/confluence/
  3. TWiki : http://twiki.org/
  4. SocialText : http://www.socialtext.com/  
  5. Springnote : http://www.springnote.com/ko

성능분석

  1. ANTS Load : http://www.red-gate.com/products/ants_load/index.htm  
  2. JunitPerf : http://www.clarkware.com/software/JUnitPerf.html  
  3. Jmeter : http://jakarta.apache.org/jmeter/

기타

  1. Structure101 : http://www.headwaysoftware.com/index.php  
  2. FreeMind : http://freemind.sourceforge.net/wiki/index.php/Main_Page  
  3. Capistrano : http://manuals.rubyonrails.com/read/book/17
출처 :   개발이 좋아 개발자가된 많은 사람들에게 말하고 싶은 이야기. by k16wire
반응형
당연히 가장 먼저 할 일은 JCL 라이브러리를 받는 것이다. 아파치 다운로드 페이지로 간다.
 
현재 최신 버전은 1.0.4 (2004년 11월 8일 기준)
 
주요 클래스(인터페이스)를 살펴 보면 딸랑 두개다. 로깅을 담당하는 인터페이스인 Log와 Log 인스턴스를 만들어내는 팩토리 클래스인 LogFactory.
 
물론, JCL은 단지 API 역할만 하기 때문에 Log 인터페이스를 상속한 Log 객체를 쓰게 될 것이다.
 
JCL에서 지원하는 로그 수위는 Log4J와 JDK의 중간인 6단계다.
  1. trace (the least serious)
  2. debug
  3. info
  4. warn
  5. error
  6. fatal (the most serious)
실제 로깅을 수행할 때, 초보자가 가장 어려운 부분은 설정일 것이고, 그 후에는 효율적인 로깅을 할 수 있는 노하우나 절차를 익히는 것이다. 설정에 대해 배워보자.
 
JCL을 사용하는 이점 중에 하나는 JCL에 대해서는 설정할 것이 없다는 점이다. 다만, 구현체로 Log4J나 JDK 로깅을 쓰기 위해 이를 위한 설정만 해주면 된다. 어떻게 이것이 가능할까? 물론, JCL에서 이러한 작업을 수행하기 때문에 가능한 것이다. JCL에 포함된 LogFactoryImpl 클래스의 아래와 같은 코드가 이러한 매직을 만드는 것이다.
 
최대한 개발자의 편의를 위해서 commons-logging.properties 파일에 사용하게될 구현체를 설정하지 않으면, 아래 분기문을 수행하면서 Log4J가 사용 가능한지, JDK1.4가 사용 가능한지, Lumberjack 로깅이 사용 가능한지를 순서대로 살펴본다. 따라서, Log4J, JDK 1.4 로깅을 사용할 경우는 JCL에 대한 별도 설정이 필요없다. 여기서 JDK 1.4 기반에서 Log4J를 사용한다면, Log4J가 사용될 것이라는 점을 짐작할 수 있다. 먼저 logClassName이 설정되고 나면, 이후의 if문에서는 선행조건인 (logClassName == null)에서 걸리기 때문이다.
 
 
        if ((logClassName == null) && isLog4JAvailable()) {
            logClassName = "org.apache.commons.logging.impl.Log4JLogger";
        }
        if ((logClassName == null) && isJdk14Available()) {
            logClassName = "org.apache.commons.logging.impl.Jdk14Logger";
        }
        if ((logClassName == null) && isJdk13LumberjackAvailable()) {
            logClassName = "org.apache.commons.logging.impl.Jdk13LumberjackLogger";
        }
        if (logClassName == null) {
            logClassName = "org.apache.commons.logging.impl.SimpleLog";
        }
        return (logClassName);
 
 
아래와 같이 로그 문장 하나를 만들어보자.
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author 안영회
 * @since 2004. 11. 8
 */
public class CommonsLoggerExample {
    private static final Log logger
     = LogFactory.getLog(CommonsLoggerExample.class.getName());

   
    public static void main(String[] args) {
       
        logger.info("hello, log");
       
    }
}
 
아래와 같은 출력문을 만날 수 있다. JDK 1.4 이상을 사용했고, Log4J를 설치하지 않았기 때문이다.
 
2004. 11. 8 오후 2:29:46 CommonsLoggerExample main
정보: hello, log
 
출력 형식과 어디에 출력할 것인가는 어떻게 결정된 것일까? JDK 설치 디렉토리 하위의 JRE/lib 디렉토리에서 logging.properties 파일을 찾을 수 있다. 여기서 JDK 로깅 관련 설정을 하게 된다.
 
############################################################
#   Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property. 
# For example java -Djava.util.logging.config.file=myfile
############################################################
############################################################
#   Global properties
############################################################
# "handlers" specifies a comma separated list of log Handler
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
logging.properties 파일의 내용이다. 천천히 살펴보자.

#   Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property. 
# For example java -Djava.util.logging.config.file=myfile
 
디폴트 로깅 설정 파일이라는 것이고, -D 옵션을 넣어서 실행하여, java.util.logging.config.file 프로퍼티를 키로 설정 파일을 다른 것으로 지정할 수 있다는 것이다.

#   Global properties
# "handlers" specifies a comma separated list of log Handler
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
 
전역 설정. 즉, 로깅 전체에 영향을 미치는 설정을 나타낸다. handlers 프로퍼티는 로그 Handler 클래스 설정에 사용되는데, 로그 핸들러(log handler)가 여러 개인 경우에는 콤마로 구분하여 나열한다. 로그 핸들러 클래스는 당연히 클래스패스에 위치해야 하고, 디폴트는 INFO 이상의 로그 수위만 화면에 출력하는 ConsoleHandler이다.
 
# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO
 
모든 로거에 기본적으로 적용할 로그 수위는 INFO라는 것이다.
 
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
 
특정 핸들러에만 적용시킬 프로퍼티. 자세한 내용은 파일 로거를 쓰면서 확인해보자.

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
특정 퍼시리티에만 적용시킬 프로퍼티, 핸드러별 설정보다 더 미세하게 특정 로거단위로도 설정이 가능하다.
 
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
 
위와 같은 설정을 아래처럼 바꿔서 파일 로그 핸들러도 쓰이도록 해보자.
 
# show messages at the INFO and above levels.
# handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
 
어디에 출력이 되었을까? 힌트는 logging.properties 파일의 파일 핸들러 관련 설정이다.
 
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
 
%h는 뭔가? JDK FileHandler API 문서에서 설명을 찾을 수 있다.
  • "/" the local pathname separator
  • "%t" the system temporary directory
  • "%h" the value of the "user.home" system property
  • "%g" the generation number to distinguish rotated logs
  • "%u" a unique number to resolve conflicts
  • "%%" translates to a single percent sign "%"
     
    %hHome directory를 의미하는 것이다. 운영체제 그리고 윈도우의 경우는 버전에 따라 디렉토리가 조금씩 다르다. 기본적으로 NT 기반인 경우(필자는 XP Pro), "C:Documents and Settings로그인한 사용자 이름"이다. 홈 디렉토리 밑에 java로 시작하고, %u에 따라 파일이름에 의한 충돌을 방지하기 위한 일련번호를 붙힌다. 확장자는 log.
     
    그래서, 필자의 경우는 홈 디렉토리에 java0.log라는 파일이 생겼다. 다른 위치에 파일이 출력되도록 변경해보자.
     
    java.util.logging.FileHandler.pattern = mylog_%u.log
     
    위와 같이 변경한 후 로그가 출력되는 프로그램을 실행시키자. 클래스 파일을 실행시킨 위치에 mylog0.log라는 이름으로 파일이 생길 것이다. 나머지 설정들의 의미를 알아보자.
     
    java.util.logging.FileHandler.limit = 50000
    하나의 파일에 최대로 기록될 바이트수를 대략적으로 지정한 것이다. 디폴트는 0이며, 무제한이다.

    java.util.logging.FileHandler.count = 1
    출력파일을 몇 개 사용할 것인가. 디폴트는 1.

    java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
    출력 포맷을 결정하는 포맷터 클래스. 기본적으로 SimpleFormatter와 XMLFormatter가 있으며, 디폴트는 XMLFormatter이다.
     
    SimpleFormatter를 사용한 경우의 출력과 XMLFormatter를 사용한 경우의 출력은 아래와 같다.
     
    SimpleFormatter 사용시
    2004. 11. 8 오후 4:49:34 CommonsLoggerExample main
    정보: hello, log
     
    XMLFormatter 사용시
    <?xml version="1.0" encoding="x-windows-949" standalone="no"?>
    <!DOCTYPE log SYSTEM "logger.dtd">
    <log>
    <record>
      <date>2004-11-08T16:37:25</date>
      <millis>1099899445360</millis>
      <sequence>0</sequence>
      <logger>CommonsLoggerExample</logger>
      <level>INFO</level>
      <class>CommonsLoggerExample</class>
      <method>main</method>
      <thread>10</thread>
      <message>hello, log</message>
    </record>
    </log>
     

  • 반응형

    이클립스 문서 번역 사이트(노트)
    퍼온곳: http://silent.springnote.com/pages/98847

    출처 : http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html

    설치를 간편하게 하기 위해선 기존 eclipse 는 그대로 두고 아래 올인원 패키지를 다운받으시는걸 추천

    http://www.eclipse.org/tptp/home/downloads/

      Copyright © 2006 International Business Machines Corp.

     Eclipse Corner Article

     

    TPTP 를 이용한 자바 어플리케이션 프로파일링

    요약
    이클립스 테스트 & 성능 툴 플랫폼 (TPTP) 프로파일링 툴은 이클립스 플러그인을 프로파일하기 위해 사용할 수 있다. 로컬 자바 어플리케이션은 물론 여러 개의 호스트나 서로 다른 플랫폼에서 동작하는 복잡한 어플리케이션에도 가능하다. 이 툴은 이클립스에 통합되어 있으며, 이클립스 상에서 동작하는 어플리케이션의 프로파일링을 해준다.
    이 문서는 TPTP 프로파일링 툴을 가지고 문제가 있는 동작을 확인하기 위해 자바 어플리케이션을 프로파일 하는 방법을 설명한다. 프로파일 세션을 시작하는 방법, 데이터 분석을 위한 다양한 TPTP 뷰를 사용하는 방법, 실행 시간이 긴 메소드를 확인하여 성능 문제를 해결하기 위해 소스 코드로 이동하는 것까지 보여준다.
     
    By Valentina Popescu, IBM
    February 21, 2006 (updated July 11, 2006)
     
    번역 : 이상훈(calm1979@gmail.com)
    2007 4 7

     

    어플리케이션 프로파일링

    지금처럼 제품을 만들어 내기 위한 단기적인 개발 사이클을 돌고 있는 상황에서는, 개발자들이 테스트, 디버깅, 코드 수정을 통한 함수의 기능적인 측면에만 중점을 두는 경향이 있다. 그러나, 대다수의 문제는 어플리케이션이 (하루 24시간, 일주일에 7일 그리고 예상치 못한 피크 타임에의 한계까지 도달하게 되는) 실제 제품으로 동작할 때까지 쉽게 드러나지 않는다.

    이런 류의 성능 문제는 디버깅 단계에서는 볼 수 없는 것들이다. 제품을 배포하기 전에 실제 상황에서 돌려보는 것이 중요하다. 어플리케이션의 동작을 분석하고, 병목현상, 객체 누수, 시스템 자원 제한 같은 성능 문제를 찾아내기 위해 프로파일링 툴을 사용하는 것은 중요하다.
    이 문서는 TPTP 프로파일링 툴을 소개한다. 그리고, 성능 문제를 확인하고 수정, 검증하기 위해 자바 어플리케이션을 프로파일링 할 수 있도록 TPTP 프로파일링 툴의 사용법을 설명한다.

    TPTP 프로파일링 툴

    이클립스 테스트 & 성능 툴 플랫폼 (TPTP) 프로젝트는 병목현상, 객체 누수 그리고 시스템 자원 제한 같은 성능 문제를 확인하고 처리할 수 있는 프로파일링 툴을 제공한다. 이 툴은 단순한 독립적인 자바 어플리케이션부터 이클립스 플러그인까지 혹은 서로 다른 플랫폼이나 다양한 머신에서 돌아가는 복잡한 엔터프라이즈 어플리케이션까지 목표로 한다.

    이클립스 프로젝트와 완벽하게 통합되어 있기 때문에, 사용하기 쉽고 확장하기도 쉽다. 이것은 사용자가 자신의 데이터 분석 화면을 붙일 수도 있고, 데이터 수집 에이전트에서 자신의 구현을 통해 데이터 수집 메타포어(metaphor)를 확장할 수 있음을 의미한다.

    이 문서는 이클립스 3.2.0을 필요로 하는 EMF 2.2.0 과 XSD 2.2.0 기반으로 하는 TPTP 4.2.0 을 사용해서 작성했다. 여기에서 이것들을 구할 수 있다. TPTP 4.2.0 설치를 위한 설명을 보려면 TPTP 다운로드 페이지 로 가면된다.

    TPTP 를 이용한 자바 어플리케이션 프로파일링

    이 문서에서 사용한 제품 카탈로그 샘플 어플리케이션은 각각의 xml 파일에 저장된 제품 정보를 분석해서 콘솔 화면에 결과를 출력하는 간단한 자바 어플리케이션이다. 제품 정보를 포함하는 xml 파일들이 위치한 디렉토리 경로는 Product.java 프로그램의 인자로 주어진다. 제품 정보를 포함하고 있는 xml 파일들은 예제 실행하기에서 제공한다.

    프로파일링 모드로 어플리케이션 시작하기

    샘플 어플리케이션을 설치한 후에, 첫 단계로 제품 카탈로그 어플리케이션을 프로파일링 모드로 실행한다. 아래 그림 1처럼 Product.java 를 선택하고 팝업 메뉴의 Profile As > Java Application 를 선택해서 어플리케이션을 프로파일한다.

    그림 1 제품 카탈로그 어플리케이션 프로파일 하기

    프로파일링 모드로 어플리케이션을 실행하는 다른 방법은 자바 퍼스펙티브의 툴바 메뉴에 있는 Profile 액션을 사용하는 것이다. Run 이나 Debug 툴바 액션 처럼, Profile 액션은 런치 설정(launch configuration) 다이얼로그를 나타낼 것이다. 다이얼로그에서 프로파일 하고 싶은 어플리케이션의 타입을 선택할 수 있다.

    자바 프로그램 인자 설정하기

    The Profile As > Java Application 을 선택하면 그림 2와 같은 런치 설정 마법사(Launch Configuration Properties wizard)가 열릴 것이다.

    이 예제에서는 제품 xml 파일의 경로를 프로그램의 인자로 넘겨준다. 이 문서의 제일 아래에서 제공되는 파일을 x:\myPath 에 풀었다고 할 경우 x:\myPath\products 를 아래 그림 2에서 보여지는 것처럼 프로그램 인자로 설정한다.

    Program arguments

    그림 2 제품 카탈로그 샘플 – 프로그램 인자(Program arguments)

    프로파일링 필터 설정하기

    다음 단계로 메소드 실행 정보를 수집하기 위한 프로파일링 옵션을 설정한다.
    이 옵션을 설정하기 위해, 런치 설정 마법사(Launch Configuration Properties wizard)의 모니터(Monitor) 탭을 선택하고, 측정하고자 하는 프로파일링 옵션을 설정한다.

    프로파일링 필터 셋(Profiling filter set)은 프로파일링 필터의 재사용 가능한 셋(set)이다. 프로파일링 필터 셋을 만드는 이유는 같은 어플리케이션을 연속적으로 실행하거나, 어플리케이션 간에 같은 종류의 프로파일링 정보를 수집하기 위해 필터 셋을 재사용하기 위함이다.
    아래에서 제품 카탈로그 어플리케이션을 프로파일 하기 위해 사용되는 새로운 필터 셋을 만드는 방법을 설명한다. com.sample.product 로 시작하는 패키지에 대해서만 사용하는 ProductFilterSet 이라는 새로운 필터 셋을 만들 것이다.

    1. 실행 정보를 수집하기 위해 모니터(Monitor) 탭에서 실행 시간 분석(Execution Time Analysis) 옵션을 선택한다.

    Execution Time Analysis option

    그림 3 실행 시간 분석(Execution Time Analysis) 옵션

    위 그림 3에서 보는 바와 같이 실행 시간 분석(Execution Time Analysis) 옵션을 선택했다. 이것은 제품 카탈로그 어플리케이션의 연속적인 실행 중에 사용될 수 있다. 이 어플리케이션의 다음 실행 때에는 “프로파일링 필터 설정하기” 단계는 건너뛸 수 있다.

    2. 프로파일링 실행 옵션을 설정하기 위해 “옵션 수정(Edit Options)” 버튼을 누른다.

    2a. "Collect boundary classes excluded by the filter set" 옵션을 선택하고 Boundary class depth 값으로 3을 입력한다.

    이 옵션을 선택함으로써, 필터 범위 내에서 실행되는 메소드들 중에 입력된 단계(depth)까지 호출되는 메소드에 대한 정보를 수집하겠다고 설정 한 것이다.

    예를 들어, MyMethod 라는 메소드에 대해 정보를 수집하도록 설정했고, M1, M2, M3, M4 메소드에 대해 필터 설정을 했다고 하자.

    다음과 같은 invocation stack 이 실행되었다고 한다면: MyMethod > M1 > M2 > M3 > M4 ( MyMethod 가 M1 을 호출하고, M1이 M2를 호출하고, M2가 M3를 호출하고, M3가 M4를 호출했다.), 2a 에서 설정한 필터 범위 값에 따라, 프로파일러는 콜 스택을 다음과 같이 보여줄 것이다: MyMethod > M1 > M2 > M3 그리고 마지막 M3>M4는 표시되지 않을 것이다. (호출 단계(depth)가 3을 초과했기 때문이다).

    Profiling Execution options

    그림 4 실행 정보 수집을 위한 설정

     

    3. 프로파일 하기 위한 클래스들을 선택하기.

         모니터(Monitor) 탭에서, 자바 프로파일링(Java Profiling) 아이템을 선택하고 옵션 수정(Edit Options)을 선택한다. 그러면 필터 셋 마법사(Filter Set wizard)가 뜬다.
    필터 셋 페이지는 프로파일 하고자 하는 클래스를 선택하기 위해 사용한다. 사용 가능한 필터들이 설정되어 있을 것이다. 그러나 이 예제에서는 com.sample.product 로 시작하지 않는 모든 패키지를 제외하는 ProductFilterSet이라고 하는 새로운 필터 셋을 만들 것이다.
    필터 셋을 만들기 위한 단계:

    3a) 필터 셋(filter set) 목록에서 추가(Add...) 버튼을 선택한다. 새로운 필터 셋의 이름을 ProductFilterSet 을 입력하고 확인(OK)을 누른다.

    3b) 그림 5에서 보는 것 처럼 두 개의 필터를 추가하기 위해 선택된 필터 셋(Contents of selected filter set) 목록에서 추가(Add…) 버튼을 누른다.

     

    Select the classes to be profiled

    그림 5 프로파일 하고자 하는 클래스 선택하기

     

     

    어플리케이션 실행하기


    런치 설정 마법사(Launch Configuration wizard)에서 확인(OK)을 누름으로써 제품 카탈로그 어플리케이션(Product catalog application)을 실행한다. 프로파일링 & 로깅(Profiling and Logging) 퍼스펙티브로 전환하겠냐는 다이얼로그가 뜨면 예(Yes)를 선택한다.
    아래 그림 6에서처럼 콘솔 화면에 프로그램 실행 결과가 출력되는 것을 볼 수 있을 것이다.

    Product application terminated

    그림 6 제품 카탈로그 어플리케이션(Product catalog application)이 실행되었다

     TPTP 프로파일링 툴은 어플리케이션과의 상호 작용을 할 수 있도록 한다. 모니터링을 일시 정지, 다시 시작 할 수 있으며, GC(garbage collection)를 실행할 수도 있고 객체 레퍼런스(object references)를 수집하거나 어플리케이션을 종료할 수도 있다.


    실행 통계(Execution Statistics) 뷰를 이용한 성능 문제 확인하기


    성능 문제를 확인하기 위해 실행 통계 뷰를 사용한다. 뷰를 열기 위해, 프로파일링 모니터 뷰에서 프로세스(process)를 선택하고 Open with > Execution Statistics 를 선택한다.
    아래 그림 7 에서 보는 바와 같이 실행 통계 뷰에서는 실행된 메소드들을 누적 시간(cumulative time)으로 정렬해서 볼 수 있다. 메소드의 누적 시간은 다른 메소드를 호출하는 것을 포함한 실행 시간이다.

    Execution statistics view

     

    그림 7 실행 통계(Execution Statistics) 뷰

    그림 7 보면, main(java.lang.String[]), readData(java.lang.String) 그리고 createParser()의 3가지 메소드가 가장 오랜 실행 시간을 사용한 것을 알 수 있다. Main과 readData 메소드가 상위에 있는 것은 걱정할 것이 아니다. 처음 것은 어플리케이션의 시작점이고, 두번째 것은 xml 파일로부터 제품 정보를 읽어들이는 것이기 때문이다.

    우리가 지켜봐야할 것은 단지 xml 파일을 파싱(parsing) 하기 위해 SAX 파서 인스턴스를 만드는 creatParser() 메소드가 높은 실행 시간을 나타내고 있다는 것이다. 이 메소드의 실행 시간이 어플리케이션의 전체 실행 시간에 42.96%나 차지한다. 실행 통계는 이 메소드가 어플리케이션의 성능을 최적화하기 위한 가능성이 있는 부분임을 알게 해준다.

    일단 이 것을 확인했으면, createParser() 메소드의 상세 실행 정보를 보기 위해 드릴 다운(drill down) 해보자.

    createParser() 메소드에서 메소드 호출 상세(Method Invocation Details ) 뷰 열기

    다음으로 우리는 createParser() 콜 스텍의 어떤 메소드가 이 메소드의 실행 시간을 느리게 하는지 보기 위해 메소드 호출 상세 뷰를 사용한다. 실행 통계 뷰에서 createParser() 메소드를 더블 클릭하여 메소드 호출 상세 뷰를 열자.

    Method Invocation Details

    그림 8 메소드 호출 상세(Method Invocation Details) 뷰

     


    그림 8에서는 createParser() 메소드의 실행 정보를 보여준다. 보는 바와 같이 이 메소드는 readData(java.lang.String)에 의해서 한 번 호출되었고 5개의 다른 메소드들을 호출함을 알 수 있다. 호출한 메소드(Selected method invokes) 테이블을 보면 newSAXParser()와 newInstance() 메소드가 createParser() 메소드를 느리게 한다는 것을 알 수 있다. createParser() 메소드가 24번 호출된 것 처럼 이 두 메소드가 24번이나 호출되었다.

    확인된 성능 문제로부터 해결책을 정의하기


    이 데이터를 분석함으로써, 우리는 createParser() 메소드의 실행 시간 향상을 위해서는 두 개의 SAXParserFactory 메소드의 샐행 향상을 해야한다는 것을 알았다. 우리는 이 메소드의 구현에 관여할 수 없으므로, 우리의 어플리케이션 실행 향상을 위해서는 이 메소들의 호출을 최대한 줄여야한다.

    해결책은 모든 파일 마다 새로운 파서를 만들지 않고, 하나의 파서 인스턴스를 만들고 이것을 재사용하는 것이다. 소스 코드를 열고 수정해보자.

    이런식의 최적화 방향을 결정하기 전에, 코드 상에서 지원을 하는지를 확실하게 해둘 필요가 있다. 예를 들어, SAXParser는 여러 쓰레드에 의해서 동시에 사용될 수 없기 때문에 인스턴스를 재사용할 수 있는 것이다. 엄격하게 말하면 인스턴스는 재사용하기 전에 reset()해주어야 한다. 변경 내용을 적용할 수 있는 코드를 작성하기 전에 포괄적인 단위 테스트 조합을 구성해두는 것도 좋은 생각이다.

     

    소스 코드를 열고 성능 문제를 수정하기

    createParser() 메소드에 대한 소스 코드를 열기 위해 메소드 호출 상세(Method Invocation Details) 뷰에서 마우스 우클릭을 하고 팝업 메뉴에서 소스 열기(Open Source)를 선택한다.

    Source code


    그림 9 소스 코드

    그림 9에 createParser() 에 대한 소스 코드가 있다. 이 메소드가 매번 호출될 때 마다 새로운 SAX 파서 인스턴스를 만드는 것을 알 수 있다.
    아래 그림 10처럼 하나의 파서 인스턴스를 만들고 모든 xml 파일을 파싱하는데에 그것을 재사용하도록 코드를 수정하자.

    Source code

    그림 10 소스 코드 수정

    그림 10에서 보는 것 처럼 전역 SAXParser 인스턴스를 만들어서 성능 문제를 해결했다. createParser() 메소드는 파서를 초기화 하고 메소드가 호출될 때 마다 만들어진 인스턴스를 리턴한다.

    다시 돌아가서 제품 카탈로그 어플리케이션을 다시 프로파일링 모드로 동작시켜 수정 내용을 검증해보자.

    성능 문제 해결 검증하기

    성능 문제 해결을 검증하기 위해, 위에서 말한 것 처럼 Product 클래스를 선택하고 우클릭해서 Profile As > Java Application를 선택한다.

    프로파일링 옵션 마법사는 나타나지 않을 것이다. 이전에 설정한 프로파일링 옵션이 어플리케이션 실행시에 사용된다. 어플리케이션을 실행한 후에 실행 통계(Execution Statistics) 뷰를 열고 실행 시간을 비교해보자.
    그림 11에 수정된 코드를 적용한 후의 실행 시간이 있다:

     

    Execution Statistics view

     

    그림 11 실행 통계(Execution Statistics) 뷰

     

    위 그림에서 보는 것처럼, 수정하기 이전에 거의 43% 였던 createParser() 메소드의 실행 시간이 단지 19%로 줄었다.
    이 성능 향상은 파싱해야될 xml 파일이 많을수록 더 커질 것이다. 따라서 카탈로그에 추가되는 제품 정보 파일이 많아질수록 어플리케이션의 실행 시간이 엄청나게 줄어들게 될 것 이다.

    결론

    이 문서에서는 TPTP 프로파일링 툴을 사용해서 성능 문제를 확인하고 해결하는 방법을 설명했다. 이 문서에서는 다루지 못한 TPTP 툴의 많은 기능이 더 있다. 만약 이 툴의 기능을 더 알고 싶다면 여기에 있는 튜토리얼 슬라이드와 사용자 가이드들을 보기 바란다.

    예제 실행하기

    "ProductCatalog_example.zip" 파일에는 이 문서에 나와있는 예제의 소스 코드를 포함하고 있다. 이클립스의 “plugins” 디렉토리에 ZIP 파일을 풀면된다. 또한 제품 xml 파일들은 products.zip 파일에 있다. products.zip 파일을 시스템의 원하는 곳에 풀어놓고, 그 경로를 제품 카탈로그 어플리케이션의 프로그램 인자로 적어주면 된다.

    Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.


    반응형
    src 디렉터리에 package 가 aaa.bbb.ccc의 형태로 되어 있을 때....

           <target name="compile">

                 <mkdir dir="${build}"/>

                 <javac destdir="${build}">

                        <src path="${src}"/>

                        <include name="**/*.java"/>

                 </javac>

                 <copy todir="${build}/aaa/bbb/ccc">

                        <fileset dir="${src}/aaa/bbb/ccc">

                               <include name="*.xml"/>

                               <include name="*.jsp"/>

                        </fileset>

                 </copy>

           </target>

    컴파일(javac)의 경우에는 destdir에 하위 폴더를 지정해주지 않아도 자동 생성된다.
    그러나 copy의 경우에는 하위폴더를 지정해주지 않는다면
    (만약 copy todir="${build}" 라고만 한다면 build 디렉터리에 카피될 것이다.

    + Recent posts