Whiteship's Note


OSAF 샘플 코드 실행하기(스크린캐스팅)

OSAF : 2008.10.28 23:44



top


EJ2E Item 6. 사용하지 않는 객체 레퍼런스를 제거하라

Java : 2008.10.28 16:18


참조: Effective Java 2nd Edition Item 6. Eliminate obsolute object references

C나 C++처럼 메모리 관리를 직접 하다가 GC를 사용하는 자바로 넘어오면 편해진거 같지만, 조심하지 않으면 메모리 부족 현상이 나타날 수 있다.

public Object pop() {
  if (size == 0)
    throw new EmptyStackException();
  return elements[--size];
}

배열에서 필요없는 객체 레퍼런스를 가지고 있기 떄문에, 여러 객체를 담고 빼고 하다보면 계속 쌓여서 결국엔 메모리 부족 현상이 발생한다.

public Object pop() {
  if (size == 0)
    throw new EmptyStackException();
  Object result = elements[--size];
  elements[size] = null; // Eliminate obsolete reference
  return result;
}

명시적으로 null 로 설정하는 방법은 예외적인 경우에 한해서 사용하는게 좋다. 객체 레퍼런스를 제거하는 가장 좋은 방법은 scope를 이용하는 것이다. 자연스럽게 제거 되도록..

또 다른 메모리 부족 주요 원인은 캐시.

객체 레퍼런스를 캐시에 넣어두고 삭제하는 걸 깜빡하는 경우가 있다. 대안책으로 WeakHashMap을 사용하는 것이다.
Remember that WeakHashMap is useful only if the desired lifetime of cache
entries is determined by external references to the key, not the value.
흠.. Weak Reference를 사용하는 HashMap인것 같은데, 잘 몰겠다. API를 봐야겠네.

메모리 부족 세 번째 주요 원인은 리스너나 콜백.

콜백을 등록하고 나서 나중에 해지할 때 제대로 하지 않아서 문제 발생. 콜백을 GC 하는 최선의 방법은 WeakHashMap을 사용해서 콜렉션에 오직 weak reference만 담는 것이다.

메모리 부족 문제는 힙 프로파일러(heap profiler)를 사용해서 디버깅 하지 않는 이상 찾아내기 힘들다.

top


EJ2E Item 5. 불필요한 객체 생성 방지하기

Java : 2008.10.28 12:09


참조: Effective Java 2nd Edition Item 5. Avoid creating unnecessary objects

객체를 매번 새로 생성하는 것보다 재사용하는게 당연히 더 빠르고 적절한 방법이다.

String s = new String("stringette"); 이렇게 쓰지 말것.

위 방법은 매번 새로운 String 객체 생성한다.

String s= "stringette"; 이렇게 쓸 것.

이 방법은 매번 하나의 String 객체를 사용한다. 또한 이 경우 VM에 같은 문자열을 참조하는 코드가 있을 때 같은 객체를 재사용한다.[JLS, 3.10.5]

static factory method[item 1]를 사용해서 조정할 수 있다. 생성자를 사용하면 무조건 새로운 객체를 생성하지만, 이 녀석은 꼭 그래야 하진 않으니까.

mutable 객체 재활용하는 방법
- static initialization.

private static final Date BOOM_START;
private static final Date BOOM_END;

static {
  Calendar gmtCal =
    Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
  BOOM_START = gmtCal.getTime();
  gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
  BOOM_END = gmtCal.getTime();
}

1.5에서 불필요한 객체를 생성하게 된 경우.
- autoboxing/unboxing.
- primive 타입을 사용 선호하고, 의도하지 않은 autoboxing을 하지는 않는지 조심해야 한다.

// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
  Long sum = 0L;
  for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i;
  }
  System.out.println(sum);
}

(캬오.. 위 코드에 그렇게 심각한 문제가 있었다니.. ㄷㄷㄷ...)

이번 Item을 읽으면서 주의할 것은 객체 생성이 굉장히 비싼 일이고 기피해야 할 것은 아니라는 것이다. 코드를 보다 분명하게 하고, 간단하게 하기 위해 객체 생성을 명시적으로 하는 것은 괜찮다.

반대로 비싼 객체를 자신만의 객체 풀(object pool)을 만들어서 관리하려는 건 비추한다. 객체 풀 관리하다가, 메모리 잡아먹고, 성능 문제가 생길 수도 있다.

top


EJ2E Item 4. private 생성자로 객체생성 방지하기

Java : 2008.10.28 11:00


참조: Effective Java 2nd Edition Item 4. Enforce noninstantiability with private constructor

때로는 static 메소드나 static 필드만 가지고 있는 클래스를 작성하고 싶을 떄가 있을 것이다. (ㅇㅇ. XXUtils 같은 클래스들이 그런 경우겠다.)

이때 abstract 클래스로 만드는 건 효과가 없다.
- 상속 받아서 객체 생성할 수 도 있으니깐..
- 또 abstract를 보면 왠지 상속받아서 사용하도록 만들어둔 클래스로 생각하게 한다.

public class UtilityClass {
  // 객체 생성 방지
  private UtilityClass(){
    throw new AssertionError();
  }
}

명시적으로 기본 생성자라를 private으로 설정한다.
- 생성자 안에서 던지는 AssertionError는 보험.
- 반직관적이기 때문에 생성자에는 주석을 달아주는게 좋다.
- 상속 받아도 소용없다. 명시적이든 암묵적이든 상위 클래스 생성자를 호출할테니까..

top


OpenSprout IRC 서버로 오세요.

OSAF : 2008.10.28 09:50


원문: http://www.opensprout.org/wiki/pages/viewpage.action?pageId=2162739

Introduction

OpenSprout에서 발표한 OSAF 프레임워크나 Spring에 대해서 질문이나 의견 나누실 분들 또는 다른 개발자들과 이런 저런 채팅을 원하시는 분들은 언제든 환영합니다. IRC서버 운영이 생전 처음이라 미흡한 점이 있을 것 같아 일단 KSUG분들을 중심으로 시범 운영해보려고 합니다.

How-to

IRC 클라이언트 설치

mirc같은 상용 제품도 있지만, 파이어폭스 플러긴 Chatzilla를 이용할 수도 있습니다. 파이어폭스 기준으로 설명하겠습니다.

  • 도구 -> 부가기능 클릭
  • 전체검색 탭 클릭
  • irc로 검색
  • chatzilla 설치 및 파폭 재시작.

Chatzilla 설정하기

위에서 Chatzilla를 설치했다면, 이제 도구 -> Chatzilla 메뉴가 생겼을 겁니다. Chatzilla를 이용해서 클라이언트 프로그램을 실행하면 조그만 창이 뜹니다.

일단 설정 화면(ChatZilla -> Preference)에 들어가서 인코딩 설정을 해줍니다.

부가적으로 Gloval 탭의 중간쯤에 알람 설정을 할 수도 있습니다. 다른 사용자가 메시지를 입력했는지 알고 싶다면 해당 탭에서 beep 또는 wav 파일 위치를 설정하면 됩니다.

이제 채팅하기

/server www.opensprout.org

이렇게 OpenSprout IRC 서버로 접속합니다. 접속이 되면,

/list

list 명령어로 현재 개설된 채널을 확인할 수 있습니다. OSAF 채널은 항상 열려있습니다. 따라서,

/join OSAF

이렇게 OSAF 채널로 들어오시면 됩니다.


top


EJ2E Item 3. 싱글톤 속성은 private 성성자 또는 enum 타입으로

Java : 2008.10.28 09:41


싱글톤은 객체를 딱 한번만 생성하는 클래스.

1.5 전에 싱글톤을 구현하는 방법은 두 개였다. 둘 다 private 생성자와 public static 멤버를 노출한다.

첫 번째 방법: public static filed

public class Elvis {
  public static final Elvis INSTANCE = new Elvis();
  private Elvis(){...}
  ...
}

private 생성자는 딱 한 번 static final 필드인 Elvis.INSTANCE를 초기화할 때만 호출한다. 한 가지 주의 할 것이 있는데...
a privileged client can invoke the private constructor reflectively
(Item 53) with the aid of the AccessibleObject.setAccessible method
이 부분 잘 모르겠슴.

두 번째 방법: public static factory method

public class Elvis {
  private static final Elvis INSTANCE = new Elvis();
  private Elvis(){...}
  public static Elvis getInstance() { return INSTANCE; }
  ...
}

위에서 잘 모르는 부분의 문제가 이렇게 하면 발생하지 않아. (OSAF도 이런식으로 싱글톤을 만들었쥐.) 좀 더 유연하게 변경할 수 있다. Generic 타입을 고려할 수 있다.(Item 27) 이것도 모르겠군.

위의 두 가지 방법은 Serializable 하지 못한다. (static 필드는 직렬화 안 되니깐) 따라서 모든 객체 필드를 transient로 선언하거나 readResolve 메소드(Item 77)를 제공해야 한다.

세 번째 방법: Enum singleton

1.5 부터 사용할 수 있는 싱글톤 구현 방법. 캬.. 드디어 새로운 방법 등장이구나.

public enum Elvis {
  INSTANCE;
  ...
}

이 방법은 기능적으로는 public filed 접근 방법과 동일하지만, 간결하고, 여러 객체를 생성할 여지도 없으며, 직렬화도 제공한다는 점에서 차이가 있다.
a single-element enum type is the best way to implement a singleton
저자가 이 정도로 권장할 정도니까.. 사용해 봐야겠다.
top