고친 과정 | |
---|---|
고침 $Revision: 1.2 $ | $Date: 2002/09/27 09:33:28 $ |
이 장의 목적은 MX4J 개발자들에게 시작할 공통적인 기반을 제공하는 몇가지 제안을 제공하는데 있다. 더 나아가, MX4J 새 릴리즈를 만들고 배포하는 공통 지시(indication)을 제공한다.
Java에 대한 코딩 관례는 시작하는 기반이다. 여기를 참고 온라인 괄호 하나 스타일의 추가적인 관례를 필요로 한다 :
예 7.1. One-line one-brace style
public class Main { // bad private String name; public Main(String n) { // bad if (n != null) { // bad name = n; } } } public class Main { // good private String name; public Main(String n) { // good if (n != null) { // good name = n; } } }
코드에 로깅 문을 집어넣는 것은 디버깅을 돕고, 프로그램이 무엇을 하고 있는지에 대한 정보를 기록할 수 있는 좋은 예제가 된다.
MX4J는 사용법이 Log4J project의 Category클래스와 매우 유사한 mx4j.log.Logger클래스에 기반하는 built-in 로깅시스템을 가지고 있다.
Logger 클래스는 다른 priority를 가지는 여섯개의 메소드를 가진다. 낮은 우선순위부터 높은 순위로 :
public void trace
(...);
public void debug
(...);
public void info
(...);
public void warn
(...);
public void error
(...);
public void fatal
(...);
Logger 클래스는 Logger인스턴스에 대한 우선순위 설정을 반환하는 유용한 메소드를 가진다 :
public boolean isEnabledFor
(...);
예 7.2. run-time시 String 연결 비용 줄이기
Logger logger = ...; if (logger.isEnabledFor(Logger.TRACE)) { logger.trace("Result is: " + result + " on item: " + item + " for process: " + process); }
String 객체 생성을 피하는 또 다른 유용한 방법은 아래 예제와 같이 StringBuffer 클래스를 사용하는 것이다 :
예 7.3. StringBuffer를 사용하여 String 연결의 run-time비용 절약하기
Logger logger = ...; if (logger.isEnabledFor(Logger.TRACE)) { StringBuffer message = new StringBuffer("Result is: ").append(result).append(" on item: ").append(" for process: ").append(process); logger.trace(message); }
Logger 클래스의 인스턴스를 어떻게 얻을 수 있을까? mx4j.log.Log를 다음 방법으로 사용하여야 한다.
예 7.4. Logger 인스턴스 가져오기
Logger logger = Log.getLogger("MyCategory");
적절한 우선순위를 선정하는 것은 중요하며, 몇가지 가이드라인이 있다 :
Logger.trace
는 실행 플로우를 log하기위해
사용한다. 항상 Logger.isEnabledFor
를 호출하는 곳 안에 trace 순위의 로그를 남긴다.
Logger.debug
는 변수의 값을 log하기 위해 사용한다.
항상 Logger.isEnabledFor
를 호출하는 곳 안에 trace 순위의 로그를 남긴다.
Logger.info
는 사용자가 관심을 가질 수 있�f
정보를 log하는데 사용한다. 모든 public 메소드는 적어도 하나의 info 순위의 log를 가져야 한다.
항상 Logger.isEnabledFor
를 호출하는 곳 안에 trace 순위의 로그를 남긴다.
Logger.warn
는 정상적인 상황에서는 발생해서는
안되는 복구가능한 에러에 대한 로그에 사용한다. warn 순위는 MX4J의 디폴트 순위이다.
Logger.error
는 exception을 로그한다.
일반적으로 error 순위는 catch 블럭안에 log가 있으며, rethrowing 하기전에 사용한다.
예 7.5. error 순위에서의 로그
Logger logger = ...; try { thisMethodThrows(); } catch (Exception x) { logger.error("Exception happened: ", x); throw x; }
Logger.fatal
(...);는 JVM이 종료될 에러를
log하는데 사용되낟. 일반적으로 log는 catch 블럭내에서 사용되며, System.exit
를 호출하기 전에 사용된다.
예 7.6. fatal 순위 로그 사용
Logger logger = ...; try { Class.forName("java.lang.Object"); } catch (ClassNotFoundException x) { logger.fatal("Can't find core classes", x); System.exit(1); }
System.exit
는 절대로
호출되어서는 안된다.
MX4J와 함께 제공되는 문서는 DocBook를 사용하여 작성된다. DocBook을 사용하는 것은 매우 쉽고, 온라인 매뉴얼이 여기 있다
일반적으로, 레이아웃은 index.xml에 정의된다. 다른 파일들은 장에 속하는 DocBook 섹션들이며, index.xml에 정의된다.
모든 섹션은 작성자와 revision history를 에 대한 정보를 가지는 sectioninfo를 호함해야 한다. 문단을 섹션에 추가하는 모든 작성자들은 authors의 리스트에 추가하여야만 하며, tag의 revnumber와 date는 CVS 키워드 $Revision$와 $Date$ 포함하여야 한다. 이렇케 하여 모든 섹션은 CVS에 의해 매 commit시 자동적으로 update될 수 있을 것이며, reader는 즉시 이 문서가 얼마나 되었는지 알 수 있을 것이다.
MX4J를 릴리즈하는 데에는 다음과 같은 절차가 필요하다.
MX4J JMX 에이전트의 기본 구현 클래스는 mx4j.server.MBeanServerImpl이다.
MBeanServer 구현 클래스는 다음의 역할을 수행한다 :
JMX 에이전트에 대한 정보는 getDefaultDomain()
나 mx4j.server.MBeanServerImpl클래스에
직접 구현된 여러가지 메소드를 통해서 제공될 수 있다.
등록된 MBean들은 저장소에 보관된다.
MBeanServer구현은 저장소 작업을 명시한 mx4j.server.MBeanRepository인터페이스의 구현을
위임 수행한다. 따라서, MBeanServer 구현은 MBeanRepository 객체에 대한 factory로서
동작할 수 있다. 하지만, 실제 구현은 MBeanRepository 객체에 위임한다.
MBeanRepository는 시스템 프로퍼티 "mx4j.mbeanserver.repository"에 구현된 클래스의 전체 이름(FQN)을 명시하여
다른 MBeanRepository 구현 클래스로 대체하는 것이 가능하다.
MBean이 등록될 때, MBean의 MBean호환인지 아닌지, MBeanInfo 정보를 가져올 것인지등,
형을 알아내기 위해서 몇가지 체크가 이루어 져야 한다.
MBeanServer 구현은 이런 작업을 mx4j.server.MBeanIntrospector클래스에 위임한다.
이 클래스의 객체는 먼저 주어진 MBean에 대한 완벽한 조사를 요청한다.
MBeanIntrospector가 MBean에 대한 모든 정보를 수집하면, mx4j.server.MBeanMetaData
클래스의 인스턴스가 된고, MBeanServer 구현은 MBeanIntrospector를 통해서 MBean 호환인지를 체크하게 된다.
MBean이 표준 MBean이면, MBean 관리 인터페이스나 MBean invoker를 생성하는데
사용하기 위해서 MBeanIntrospector는 MBeanInfo 정보를 생성해야 한다. 아래를 보자.
MBeanIntrospector의 역할은 이렇케 MBean 호환성을 체크하고, 표준 MBean에 대해 MBeanInfo 정보를 생성하며,
MBean Invoker에 대한 factory로서 동작하는 것이다.
MBeanServer 구현은 사용자 편의를 위해서 등록된 MBean들의 operation invoker로 동작한다.
구조는 가로채기(interceptor)기반이고, 클라이언트에서 호출하면, MBeanServer 메소드는 MBean 인스턴스를 호출하고,
이것이 interceptor 체인에 보내지게 되며, 궁극적으로는 MBean 인스턴스에 전달된다.
인터셉터들은 MBeanServer 인터셉터 설정자 MBean을 통해서 설정이 가능하고,
이것은 "JMImplementation" 도메인에 등록된
mx4j.server.MBeanServerInterceptorConfigurator 클래스의
하나의 MBean이다.
호출이 MBean 인스턴스에 막 도착할 때, 마지막 인터셉터는 MBean 형태에 대라 호출을 보낸다.
만약 MBean이 dyanamic MBean이면 호출은 직접 DynamicMBean의 메쏘드를
사용하고, MBean이 standard MBean이면 MBean 실행자(invoker)가
MBean 인스턴스의 메쏘드를 실행하게 된다.
MBean 실행자는 mx4j.server.MBeanInvoker 인터페이스를 구현한 것이다.
2가지 기본 MBean 실행자가 있다. 첫번째는 reflection을 기반으로 하여 MBean 인스턴스를 실행하고,
두번째는 실시간으로 생성된 클래스를 바로 실행시킨다.
이 실시간으로 생성된 클래스는 등록시에 생성된다.
이것의 바이트코드(bytecode)는
Byte Code Engineering Library를
사용하여 실시간으로 생성된다.
이 두가지 버전은 MBean 정보를 위해 빠른 캐쉬를 이용한 삼중트리에 사용된다.
따라서 standard MBean이 실제 빠르다.
성능 벤치마크는 실시간으로 생성된 버전이 reflection 버전보다 2배 정도 빠르다.
자세한 정보는 언급된 클래스에 대한 Javadoc API을 참고하시오.