월별 글 목록: 2011년 3월월

Playframewrok 시작하기..

1. http://www.playframework.org에서 최신 바이너리를 다운 받아서 압축을 풀고, play-1.x.x폴더를 /usr/local/play-1.x.x에 복사를 한다.

2. $PATH에 /usr/local/play-1.x.x를 잡아준다.

3. 새로운 프로젝트를 생성한다.

play new project

4. eclipse에서 불러오기 위해서 eclipse 프로젝트 정보를 만든다.

play eclipsify project

5. 프로젝트 구동

cd /project
play run

restfb 로그 console에 찍히는거 제거..

restfb 라이브러리가 로그를 log4j에서 java.util.logging 패키지로 바꿨네요.. ^^;; log4j에 대한 의존을 하지 않아서 깔끔하긴 한데.. 모랄까.. 실제적(?)이지 않다고 해야 하나? restfb에서 log를 console에 찍히지 않게 하려면 아래의 logging.properties 파일을 만들고 java를 실행할 때, 옵션으로 설정파일을 읽어주면 됩니다.

ex) java -Djava.util.logging.config.file=./conf/logging.properties -Xms128m -Xmx1024m -server -jar xxx-xxx-server.jar
logging.properties

############################################################
# logging.properties
# usage : java -Djava.util.logging.config.file=logging.properties
############################################################

handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level= ALL
########### level ##########
# SEVERE
# WARNING
# INFO
# CONFIG
# FINE
# FINER
# FINEST (최저치)
#############################

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user’s home directory.
java.util.logging.ConsoleHandler.level = WARNING
java.util.logging.FileHandler.pattern = /var/justin/mywho-livefeed-qserver/restfb_%u.log
# 10240000 == 10M, 102400000 == 100M, 1024000000 == 1G
java.util.logging.FileHandler.limit = 1024000000
java.util.logging.FileHandler.count = 5
java.util.logging.FileHandler.append = true
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = SEVERE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
com.restfb = INFO

우분투(Ubuntu)에서 정적(static) IP 설정

우분투에서 정적 IP를 설정하는 방법이다.

1. 설정 파일을 연다.

sudo vim /etc/network/interfaces

2. 설정 파일을 아래와 같이 수정한다.

# The primary network interface
auto eth0
iface eth0 inet static <-- dhcp를 static으로 수정, 아래는 ifconfig해서 보이는 정보 입력.. 
address 192.168.0.100
netmask 255.255.255.0
network 192.168.0.0
broadcast 192.168.0.255
gateway 192.168.0.1

3. 네트웍을 다시 시작한다.

sudo /etc/init.d/networking restart

 

자바(Java)에서의 LRUCache 메모리릭과 해결방안..

LRU(Least Recently Used)는 페이지를 사용하는 운영체제에서, 새로운 페이지를 할당하기 위해서 마지막에 사용한 페이지를 교체하는 알고리즘이다. LRUCache는 LRU 알고리즘을 이용하는 캐시클래스라고 보면 되겠다. 여기에서는 많이 사용하는 LRUCache 형태를 살펴보고, 이 형태가 가지고 있는 문제(메모리 릭)를 해결해 보자.

1. LRUCache 구현 방법

1.1 LinkedHashMap을 사용해서 만들기

final int MAX_ENTRIES = 100;
Map cache = new LinkedHashMap(MAX_ENTRIES+1, .75F, true) {
    // This method is called just after a new entry has been added
    public boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_ENTRIES;
    }
};

1.2 LinkedHashMap을 상속해서 만들기
대체로 아래의 코드가 많이 보이다. 얼핏 보기에는 잘 동작할 것으로 보인다. 하지만 시간이 지나면서 문제(메모리 릭)가 발생하게 된다.

public class LRUCache<K,V> extends LinkedHashMap<K,V> {
    private int lruSize;

    public LRUCache(int size) {
        lruSize = size;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > lruSize;
    }
}

2. 해결책
해결책을 찾아보니, https://code.google.com/p/reflection-dsl/source/browse/trunk/ReflectionDsl/src/br/com/bit/ideias/reflection/cache/LRUCache.java?spec=svn204&r=204 에서는 Value에 해당하는 객체를 SoftReference(참고로, 이넘으로 객체를 래핑하게 되면 풀 GC가 읽어날때 GC대상이 된다)로 래핑해서 GC에게 위임(?)하고 있네요..

개인적으로는 명시적으로 객체를 삭제해서 메모리릭을 방지하는게 좋다고 생각한다. 잠재적인 메모리릭을 방지해 주는 코드는 아래에서 볼 수 있다.

protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
	boolean isRemove = size() > maxsize;

	if (isRemove) {
		Object obj = this.get(eldest.getKey());  
		if(obj instanceof BufferedWriter) { // V가 BufferedWriter 인스턴스임.. 
			try {
				((BufferedWriter)obj).close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		this.remove(eldest.getKey());
	}

	return isRemove;
}

이상, 자바에서 LRU 형태의 캐시클래스를 만들 때 주의가 필요한 내용을 살펴봤다.