1. Delete the site.xml file in your Eclipse directory.
와 같이 하면 됩니다 ^^
본문서는 자유롭게 배포/복사 할수 있지만
이문서의 저자에 대한 언급을 삭제하시면 안됩니다
저자 : GoodBug (unicorn@jakartaproject.com)
최초 : http://www.jakartaproject.com
=============================================
I. 들어가면서.. 그리고 log4j
log4j는 자바 어플리케이션에서 빠르고 효과적으로 로깅 할 수 있도록 도와주는 오픈 소스 프로젝트입니다.
로깅(logging)은 코드의 가독성을 떨어뜨리는 단점이 있지만 애플리케이션에 문제가 있을 때 개발자가 자세한 상황을 파악할 수 있도록 해 주며 테스팅시 빠질 수 없는 요소입니다.
아마도 여러분들은 여러 어플리케이션이 추가되면서 각 개발자들만의 독특한 로깅방식이 서로 썩이고 얽혀서 화면에 나타나는것을 많이
봤을겁니다 -_-;
즉 로깅방법을 통일할 필요가 있는것이죠. 모든 개발자가 특정 포맷에 맞추어서 로깅 한다면 한결 로깅하기도
편하겠지요
오픈 소스 프로젝트인 Log4j는 개발자들이 매우 손쉽고 다양한 형태로 로깅을 할 수 있도록 도와줍니다. 성능또한 우수해 더이상
System.out.println을 사용할 필요가 없습니다.
II. 다운로드
다운로드 http://logging.apache.org/log4j/docs/download.html
매뉴얼 http://logging.apache.org/log4j/docs/documentation.html
API spec http://logging.apache.org/log4j/docs/api/index.html
III. LOG4J 구조
일단 log4j를 잘 모르지만 그 구조만 살짝 살펴보고 넘어갑시다
log4j는 크게 3가지 요소로 구성되며 그 구조는 다음과 같습니다
① Logger(Category) : 로깅 메세지를 Appender에 전달합니다.
② Appender : 전달된 로깅 메세지를 파일에다 기록할 것인지, 콘솔에 출력할 것인지
아니면 DB에 저장할 것인지 매개체 역활을 합니다.
③ Layout : Appender가 어디에 출력할 것인지 결정했다면 어떤 형식으로 출력할 것이지
출력 layout을 결졍합니다.
쉽죠?
IV. LOG4J 로깅 레벨
log4j는 다양한 로깅레벨을 지원합니다.
① FATAL : 가장 크리티컬한 에러가 일어 났을 때 사용합니다.
② ERROR : 일반 에러가 일어 났을 때 사용합니다.
③ WARN : 에러는 아니지만 주의할 필요가 있을 때 사용합니다.
④ INFO : 일반 정보를 나타낼 때 사용합니다.
⑤ DEBUG : 일반 정보를 상세히 나타낼 때 사용합니다.
만약 로깅 레벨을 WARN 으로 설정하였다면 그 이상 레벨만 로깅하게 됩니다.
즉 WARN, ERROR, FATAL 의 로깅이 됩니다.
V. 샘플코드 1
jsp에서 사용하는 예제가 없어 만들어 봤습니다.
test.jsp <%@ page
contentType="text/html;charset=MS949" <%! <% logger.fatal("fatal2!!", new NullPointerException("널입니다요")); logger.error("error!", new NumberFormatException()); logger.error("error!2"); logger.warn("warn"); logger.info("info"); logger.debug("debug"); |
결과 콘솔화면
① static Logger logger = Logger.getLogger("test.jsp");
static 메소드 getLogger를 통해 logger 인스턴스를 가져옵니다.
getLogger에는 파라미터로 스트링 혹은
클래스를 사용하는데 jsp에서는 클래스를 파라미터로 주기에는 좀 애매합니다. 그냥 스트링으로 주도록 하지요
②
logger.fatal("fatal!!");
logger.fatal("fatal2!!", new
NullPointerException("널입니다요"));
logger에 fatal 레벨의 메세지를 전달합니다. 다음 두가지
메소드를 지원하는군요
fatal(Object message)
fatal(Object message, Throwable t)
각 레벨마다 위처럼 두가지 메소드를 지원합니다.
지원 메쏘드 | |
logger.fatal(Object message) | logger.fatal(Object message, Throwable t) |
logger.error(Object message) | logger.error(Object message, Throwable t) |
logger.warn(Object message) | logger.warn(Object message, Throwable t) |
logger.info(Object message) | logger.info(Object message, Throwable t) |
logger.debug(Object message) | logger.debug(Object message, Throwable t) |
VI. 샘플코드 2
서블릿의 경우 다음과 같이 코딩하면 되겠군요
TestServlet.java import javax.servlet.*; public class TestServlet extends HttpServlet {
public void init(ServletConfig config) throws ServletException { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { ... } catch (Exception e) { |
VII. LOG4J 설정
log4j 설정은 프로그램 내에서 할 수 있지만 설정파일을 사용함으로서 좀더 유연하게 log4j환경을 만들 수 있습니다.
① 프로그램에서 설정
<%@ page
contentType="text/html;charset=MS949" import="org.apache.log4j.*,java.io.* " %> <%! <% PatternLayout patternlayout = new
PatternLayout(layout); |
② property 파일에
설정
log4j.properties를 만들어 /WEB-INF/classes 밑에 놓으세요
log4j.rootLogger=INFO, stdout, rolling log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender log4j.appender.rolling.File=output.log log4j.appender.rolling.Append=true log4j.appender.rolling.MaxFileSize=500KB log4j.appender.rolling.DatePattern='.'yyyy-MM-dd log4j.appender.rolling.layout=org.apache.log4j.PatternLayout log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n |
#최상위 카테고리에 INFO로 레벨 설정 및 appender로 stdout, rolling을 정의
log4j.rootLogger=INFO, stdout, rolling
#stdout 어펜더는 콘솔에 뿌리겠다는 정의
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#stdout 어펜더는 patternlayout을 사용하겠다는 정의
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#페턴은 다음과 같이 포맷팅 하겠다는 것을 정의
log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n
#역시나 rolling 어펜더는 파일로 처리한다라고 정의
log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender
#로그 파일 이름은 output.log
log4j.appender.rolling.File=output.log
#true면 톰캣을 내렸다 올려도 파일이 리셋되지 않습니다.
log4j.appender.rolling.Append=true
#파일 최대 사이즈는 500KB로 설정
log4j.appender.rolling.MaxFileSize=500KB
#파일 포맷은 output.log.2005-03-10 으로 관리하겠다고 정의
log4j.appender.rolling.DatePattern='.'yyyy-MM-dd
#역시나 rolling 어펜더는 패턴 레이아웃을 사용하겠다고 정의
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
#rolling 어펜더는 패턴 레이아웃 포맷
log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n
VIII. 설정 포맷
① 로그파일명 포맷 (DatePattern)
로그파일명 포맷입니다. 날짜, 시간 및
분단위로까지 로그 파일을 분리할 수 있습니다.
형식 | 설명 |
'.'yyyy-MM | 매달 첫번째날에 로그파일을 변경합니다 |
'.'yyyy-ww | 매주의 시작시 로그파일을 변경합니다. |
'.'yyyy-MM-dd | 매일 자정에 로그파일을 변경합니다. |
'.'yyyy-MM-dd-a | 자정과 정오에 로그파일을 변경합니다. |
'.'yyyy-MM-dd-HH | 매 시간의 시작마다 로그파일을 변경합니다. |
'.'yyyy-MM-dd-HH-mm | 매분마다 로그파일을 변경합니다. |
② PatternLayout 포맷
로그자체를 어떤 포맷으로 남길지
결정합니다.
layout에는 HTMLLayout, PatternLayout, SimpleLayout, XMLLayout등이 있으며
PatternLayout이 일반적으로 가장 많이 쓰입니다.
형식 | 설명 |
%p | debug, info, warn, error, fatal 등의 priority 가 출력된다. |
%m | 로그내용이 출력됩니다 |
%d | 로깅 이벤트가 발생한 시간을 기록합니다. 포맷은 %d{HH:mm:ss, SSS}, %d{yyyy MMM dd HH:mm:ss, SSS}같은 형태로 사용하며 SimpleDateFormat에 따른 포맷팅을 하면 된다 |
%t | 로그이벤트가 발생된 쓰레드의 이름을 출력합니다. |
%% | % 표시를 출력하기 위해 사용한다. |
%n | 플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다. |
%c | 카테고리를 표시합니다 예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다. |
%C | 클래스명을 포시합니다. 예) 클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다 |
%F | 로깅이 발생한 프로그램 파일명을 나타냅니다. |
%l | 로깅이 발생한 caller의 정보를 나타냅니다 |
%L | 로깅이 발생한 caller의 라인수를 나타냅니다 |
%M | 로깅이 발생한 method 이름을 나타냅니다. |
%r | 어플리케이션 시작 이후 부터 로깅이 발생한 시점의 시간(milliseconds) |
%x | 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다. |
%X | 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다. |
예시) (같은 색끼리 보시면 됩니다)
위의 test.jsp를 다음 포맷으로 출력해본다면
[%c] [%C] [%d] [%F] [%l] [%L] [%m] [%M] [%n] [%p] [%r] [%t] [%x] [%X]는 다음과 같다
[test.jsp] [org.apache.jsp.test_jsp] [2005-03-10 12:37:23,561] [test_jsp.java] [org.apache.jsp.test_jsp._jspService(test_jsp.java:64)] [64] [fatal!!] [_jspService] [개행] [FATAL] [765567] [http-8080-Processor25] [] []
출처 : http://cafe.naver.com/ArticleRead.nhn?articleid=69&sc=e0d433130b4a2d9c18&query=gc+java+%B8%DE%B8%F0%B8%AE&clubid=10092843
1. Sun Microsystyems의 자바 HotSpot VM은 힙을 세 개의 영역으로 나누고 있다.
힙의 세 영역은 다음과 같다:
1) Permanent space: JVM 클래스와 메소드 개체를 위해 쓰인다.
2) Old object space: 만들어진지 좀 된 개체들을 위해 쓰인다.
3) New object space: 새로 생성된 개체들을 위해 쓰인다.
New object space는 세 부분으로 다시 나누어진.
모든 새로 생성된 개체들이 가는 Eden, 그리고 그 개체들이 나이들게(Old) 되기 전에 가는 Survivor space1(From), Survivor space2(To) 가 있다.
2. Garbage Collector
프로그램은 프로그램을 진행하면서 데이터들을 저장하는 것이 필요하다.
데이터들은 모두 메모리에 저장이 되는데, 저장할 데이터가 있으면 메모리의 일정 공간을 할당받아서 사용하게 된다.
프로그램 내에서 사용하게 되는 메모리를 'heap'이라고 한다.
더 이상 사용되지 않는 데이터에게 메모리를 계속 할당해 주는 것은 메모리를 낭비하는 것이므로, 그 데이터가 사용하던 메모리를 회수하는 것이 필요하다.
이러한 사용되지 않는 메모리에 대한 회수를 'Garbage Collection'이라고 한다. 자바에서는 프로그램이 사용하는 메모리를 JVM(Java Virtual Machine)이 모두 관리한다.
3. OutOfMemory Error 및 해결방법
자바는 객체, 변수등의 생성과 동시에 메모리(Heap)를 차지하게 되고, 문제는 이 객체와 변수를 너무 많이 발생시킴으로 해서 현재 할당된 메모리(Heap)를 초과하게 된다
그래서 더이상 할당받을 메모리(Heap)가 부족하게 되면 OutOfMemory Error 발생하게 된다.
OutOfMemory Error 해결방법으로는
jdk1.4에서 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC 옵션을 사용한 GC는 현재상태의 Heap메모리 정보출력 한다.
GC정보를 통하여 New, Old, Perm 등의 영역중 실제 어느 부분이 부족하여 OutOfMemory가 발생하는지 찾은후 부족한 영역의 충분하 size를조절해 주는 방법으로 해결할 수 있다.
4. Heap layout 할당에 영향을 주는 스위치들
5. New Generation 메모리 할당 공식
Eden = NewSize - ((NewSize/(SurvivorRatio + 2)) * 2)
From space = (NewSize - Eden)/2
To space = (NewSize - Eden)/2
6. Old Generation 메모리 할당 공식
Old = Xmx - MaxNewSize
7. JVM 스위치 설정 예제
1) 현재 http://www.affis.net 서비스는 2200개의 Jsp파일을 가지고 있고 주로 정적인 페이지들이므로 Jsp 파일 로딩에 필요한 Perm size 위주로 메모리 튜닝을 하였다.
2) 현재 http://club.affis.net 서비스는 어플리케이션 동적이페이지들로 작성되어 있고 어플리케이션처리에 필요한 New size 위주로 메모리 튜닝을 하였다.
8. 맺음말
OutOfMemory 발생한다면 GC로그를 찍어본다.
로그를 분석해보면 New(eden, from, to), Old, Perm 등의 영역중에서 GC가 발생해도 메모리 영역이 계속 100%로 할당되는 영역이 보일것이다.
부족한 영역에 충분한 size 메모리를 할당해 주면 OutOfMemory 해결 된다.
그러나 부족한 영역에 계속해서 메모리 할당을 해주어도 사용률이 100%가 나온다면 프로그램 누수일수 있으니 프로그램을 점검해 봐야 할 것이다.
# java JVM Memory Perf 분석
- Tools : jvmstat-5.zip
J2SE 1.5 이상
- 구성 환경 :
Host A에 설치 동작중인 Java Applicaton( Unix )에 대한 메모리 이용율을
Host B( Windows )에서 Remote로 확인
- Host A 설치내용
J2SE 1.5 이상의 버젼이 설치 되었는지 확인
참고 : Java 1.5부터는 jvmstat의 내용이 일부 포함되어 배포가 됨.
jvmstat를 위한 Home Directory 생성 ( /usr/local/jvmstat )
$ mkdir /usr/local/jvmstat/
RMI Connection 권한 설정 파일 생성
$ cd /usr/local/jvmstat/
$ vi jstatd.all.policy
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
jvmstat를 위한 환경 변경 설정
$ export JAVA_HOME=/usr/local/java
$ export JVMSTAT_HOME=/usr/local/jvmstat
$ export PATH=$JVMSTAT_HOME/bin:$JAVA_HOME/bin:$PATH
jstatd 실행 ( jvmstat 2.0의 perfagent와 같음. )
$ cd /usr/local/jvmstat/
$ cat start.sh
#!/bin/bash
export JVMSTAT_HOME=/usr/local/jvmstat
export JAVA_HOME=/usr/local/jdk1.5.0_02
export PATH=$JAVA_HOME/bin:$JVMSTAT_HOME:$PATH
# RMI Registry Start
$JAVA_HOME/bin/rmiregistry &
# JSTAT PerfAgent Start
nohup \
$JAVA_HOME/bin/jstatd \
-J-Djava.security.policy=$JVMSTAT_HOME/jstatd.all.policy
\
-J-Djava.rmi.server.logCalls=true \
&
$ sh start.sh
local test 수행
$ jps
$ jstat -gcutil 11216 1000 10 ( 11216은 jvmps에서 vmid )
Java RMI Connection을 위한 설정
$ vi /etc/hosts
위 hostname ( backup )을 RMI로 호출될 Interface의 IP로 변경 한다.
127.0.0.1 localhost.localdomain localhost
192.168.1.117 backup
- Host B 설치 내용
J2SE 1.5 이상의 버젼이 설치 되었는지 확인
jvmstat-3.zip를 C:\에 압축 풀기 ( visualgc에 대한 내용만이 포함되어 있음. )
jvmstat를 위한 환경 변경 설정
SET JAVA_HOME="C:\Program Files\Java\jdk1.5.0_02"
SET JVMSTAT_HOME="C:\jvmstat"
SET JVMSTAT_JAVA_HOME="C:\Progra~1\Java\jdk1.5.0_02"
SET PATH=%JVMSTAT_HOME%\bat;%JAVA_HOME%\bin;%PATH%
remote test 수행 ( Host A와의 RMI 통신여부 확인 )
C:\jvmstat\bat\> jps 192.168.1.117
C:\jvmstat\bat\> jstat -gcutil rmi://11216@192.168.1.117 1000 10
- Host A의 Java Application 모니터링
상기의 설치 내용이 정상적으로 완료 확인
Host B에서
C:\jvmstat\bat\> visualgc 11216@192.168.1.117:1099 5000
11216 : vmid
192.168.1.117 : host A's IP Address
1099 : Host A's RMI TCP Port
5000 : Interval , millisecond
package com.qnsolv.wipi.exception;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ExceptionUtil
{
Log log = null;
public ExceptionUtil( Object obj)
{
log = LogFactory.getLog(obj.getClass().getName());
}
public ExceptionUtil()
{
log = LogFactory.getLog(this.getClass().getName());
}
public void writePrintStckTrace(Exception e)
{
writePrintStckTrace(e, "");
}
public void writePrintStckTrace(Exception e, String MIN)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream pinrtStream = new PrintStream(new ByteArrayOutputStream());
e.printStackTrace(pinrtStream);
String stackTraceString = out.toString();
log.error("MIN=" + MIN + ":" + stackTraceString.toString());
}
catch (Exception e2)
{
}
}
}
고층빌딩을 건축할 때 흔히 볼 수 있는 것이 타워 크레인입니다. 이 중장비는 빌딩의 뼈대가 되는 철골 구조물이나 콘크리트 벽체를 높은 곳으로 들어올려 한 층, 한 층 "조립"해 나가는데 필수적인 장비입니다. 요즈음의 빌딩들은 철골 구조물과 콘크리트 구조물을 공장에서 미리 만든 후 현장으로 옮겨와 조립하는 방식으로 만들어 나갑니다. 이러한 부품(컴포넌트)과 조립에 의한 생산방식은 근대 이후 제조업에서는 필수적인 전제 조건이 되었습니다. SW분야에서도 이러한 부품화 및 조립개념이 도입되고 있습니다. CBD(Component Based Development)가 그것입니다. 컴포넌트 다이어그램은 이러한 부품을 정의할 수 있게 도움을 주는 모델입니다. 자, 그럼 시작해 볼까요? |
| |||||||||||||||||||
여기서 컴포넌트는 매우 광범위한 의미로 사용되는 용어입니다. 여러 분야에서 쓰이는 컴포넌트의 많은 의미 중에서, SW 분야에서 사용되는 컴포넌트를 정의하면 다음과 같습니다. | |||||||||||||||||||
다음은 UML에서 정의한 컴포넌트의 정의입니다. |
| ||
(참고자료 : UML 1.3 Specification, OMG) |
|
|
|
|
|
|
|
|
|
|
|
JavaFX SDK for Windows or Mac Os X 다운로드 받아 설치합니다.
Eclipse 3.4 이상이 필요하며. Eclipse IDE for Java EE Developers for Windows or Mac OS X 설치가 필요합니다.
JAVAFX_HOME
속성값을 물어볼수도 있습니다.JAVAFX_HOME
속성 설정은 아래 단계를 따릅니다.:
JAVAFX_HOME 값을 (empty)로 추가시킵니다.
JAVAFX_HOME
변수의 세팅이 끝납니다. 만약 버튼을 누르면 에러 다이얼로그 창이 뜨며 다시 반복하여 묻게 됩니다. Eclipse 로 실행하는 것은 매우 쉽다.
Eclipse 에서의 Build 작업은 default로 자동으로 제공된다.
메뉴에서 Build와 관련된 좀 더 많은 옵션을 볼 수 있다.이 플러그인은 JavaFX SDK documentation로의 접근을 매우 쉽게 해준다. Ctrl + F1 를 누르므로서 Document에 접근 할 수 있다.