디지털 장인정신

블로그 이미지
WebKit개발자의 혼자쓰는 블로그
스페로

Article Category

All (71)
Technology (47)
Creativity (19)
Private (4)

Recent Comment

Recent Trackback

Calendar

«   2018/12   »
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          

Archive

My Link

  • Total339,105
  • Today16
  • Yesterday243
  1. 2011.02.12
    JNI inside
  2. 2010.10.05
    JAVA Server 만들기
  3. 2010.07.28
    Java책 추천
  4. 2010.05.05
    Java Reference Object의 이해와 활용 (1)
  • Java에서 JNI를 사용하여 native호출은 하나의 thread안에서 일어나는 일이다. 
  • JNIEnv로 Java method를 콜하는 방법은 pointer to pointer to 로 function table를 찾는것이다.  JNIEnv이 void**인 이유는 jni appl 컴파일 시 구현 디테일을 노출 시키고싶지 않아서 이다.
  • jni의 FindClass는 java.lang.class를 룩업한다. reflection을 이용하여 룩업한다. 룩업한 reference는 handle이다. 
  • jni에서 handle을 쓰는 이유는 객체의 pointer의 위치가 바뀔 수 있기때문이다. gc의 memory compaction 같은 작업이 그런일 을 할 수 있다.
  • jni에서 얻은 reference는 해당 함수의 frame에서만 유효하다. frame을 빠져나가면 reference의 유효함을 jvm이 보장하지 않는다.
  • 때문에 계속 쓰고 싶으면 global reference로 만들어야 한다. 다썼으면 해제하는 것을 잊지말자. gc는 global ref의 handle을 보존하기 위해 특별한 취급을 할 것이다.
  • 로컬 frame에서 만들수 있는 local reference의 수는 max는 default로 16개이다. 그 이상이 필요하다면 pushframe popframe을 사용하라.
  • methodid같은 것은 reference가 아니다. reference란 java에 객체 실체가 존재하는 것들이다.
  • jni에서 direct buffer에 접근할때 critical section임을 알려야 한다. 그래야 gc의 compaction같은것이 포인터를 바꾸는 것을 막을 수 있다.
  • 몇십개정도 entry의 짧은 배열의 경우 critical section을 잡는것 보다는 복사해서 쓰는게 낫다.
  • 보통은 java가 c를 사용하기 위해 jni를 이용하지만, c의 entry point를 갖는 프로그램도 jni를 사용하여 java를 이용할 수 있다.
  • pthread를 만들고 jvm도 만들어 attach시켜서 사용하는것이다. 그리고 jvm에게 해당 thread의 reference인 JNIEnv를 받는다.
  • 사실 java runtime을 시작하는 방법도 c의 main에서 위의 방법으로 시작하는 것이다.
  • registerNatives를 통해 jni convention과 상관없는 function을 java의 native qualifier method에 대응시킬수 있다.
  • 만약 jni 를 static으로 빌드하여 java runtime에서 실행하고 싶으면 jvm instance에 링크하여 빌드해야 한다.

'Technology > Working Note' 카테고리의 다른 글

Unicode  (0) 2011.02.23
WebKit Chromium Build in Ubuntu 10.10 64bit  (0) 2011.02.16
JNI inside  (0) 2011.02.12
Garbage collector  (0) 2011.02.12
QT WebKit Windows에서 빌드  (0) 2011.01.31
IDE 자주쓰는 단축키  (0) 2010.11.26
Trackback 1 and Comment 0

자바 서버를 만들려면 다음과 같은 방법으로 학습을 해야한다.

  1. SelectorPool, ThreadPool, ByteBufferPool, EventQueue 를 사용한 server만들기
    1. 자바 I/O NIO 의 16장 소스 활용 www.hanbitbook.co.kr/exam/1293
  2. EmberIO 사용하기 & 분석하기
    1. 소스 : http://sourceforge.net/projects/pyrasun/
    2. 아티클
      1. http://www.theserverside.com/news/1377014/EmberIO-Dispelling-NIO-Myths
      2. http://www.manskes.de/index.php/2005/03/13/some-thoughts-on-emberio-and-ejoe/

 그러면 당신도 JAVA Server 전문가~!

'Technology > Working Note' 카테고리의 다른 글

WebKit에서 새창띄우기 function flow  (0) 2010.10.18
WebKit TiledBackingStore Drawing Sequence 분석  (0) 2010.10.12
JAVA Server 만들기  (0) 2010.10.05
WebCore의 event 처리 루틴  (0) 2010.10.04
자주쓰는 git 명령어  (0) 2010.04.23
Tech Log  (0) 2010.04.10
Trackback 0 and Comment 0

< Java >
   Core Java 2 7th Edition (더 높은 Edition이 있으면 더 높은 것으로.) 
     -- 예제를 현명하게 외울정도로 익히셔요. Reference로도 굿
   Effective Java Programming Guide by Joshua Bloch 
     -- 필수! 돈이 아깝지가 않은 책!

< JUnit, TDD > 
    JUnit Recipes : Practical Methods for Programmer Testing 

< Design Pattern > 
    Design Patterns : Elements of OO software (with C++ example) 
    Applying UML and Pattern  

< Reflection > 
   Java Reflection in Action

< Spring framework / J2EE > 
   Pro Spring, 

< Thread > 
   Java Concurrency in Practice

< Design/ UML> 
   A Brief Guide to the standard object Modelling Language 

< Ant > 
   Java Development with Ant


한글책
  • 자바 프로그래밍 언어
  • THE JAVA LANGUAGE SPECIFICATION 
  • 멀티코어를 100% 활용하는 자바 병렬 프로그래밍
  • 유쾌한 자바 퍼즐러


'Creativity > Book' 카테고리의 다른 글

핵의학 길잡이  (1) 2011.06.03
Java Concurrency in Practice  (0) 2011.05.15
Debug it! 실용주의 디버깅  (1) 2011.02.19
생각하는 뇌, 생각하는 기계  (0) 2010.09.20
읽고싶은 개발 서적  (0) 2010.08.10
Java책 추천  (0) 2010.07.28
Trackback 0 and Comment 0
http://blog.naver.com/atonikkaz?Redirect=Log&logNo=10013450090 에 끝내주는 설명이 있어서 퍼왔다.

https://www.youtube.com/watch?v=N6YdwzAvwOA 를 보면 soft reference, weak reference 를 적절히 잘 사용하라고 충고한다. 예를들면 bitmap같이 용량이 크고 자주사용하는 것을 soft reference에 저장하면 out of memory가 나올 상황에 gc 가 자동으로 지워주니 너무좋은  cache방법이라고 한다. 

  • 박병권(커뮤니티 개발1팀), 2006년 10월 

초록(Abstract)

자바의 garbage collector는 더 이상 참조되고 있지 않는 객체를 자동으로 수거하여 프로그래머가 직접 메모리를 관리하지 않아도 되도록 해준다. 하지만 모든 경우에 대해 garbage collector가 깨끗하게 사용하지 않는 객체들을 정리해주는 것은 아니다. 때로는 참조가 계속 남아있는 경우가 있을 수 있고 이런 경우에 객체는 수거되지 않고 memory leak으로 이어질 수 있다. 이와 같이 참조를 부주의하게 사용하여 발생할 수 있는 memory leak현상을 막기 위해서는 객체에 대한 참조를 유연하게 다루어 필요하지 않은 객체들이 수거될 수 있도록 해야한다.

자바에서는 객체들이 소멸될 시점을 조절하고 객체 소멸에 따른 사후 작업 처리를 위해 reference object들과 reference queue를 지원하는데 이에 대해 알아보도록 하자.

Reachability #

Garbage collector는 reference root set으로 부터 참조를 통해 도달 가능한 객체들을 제외하고는 모두 garbage로 간주한다. 즉 garbage collector의 관점에서는 참조할 수 있는 객체(reachable)와 참조할 수 없는 객체(not reachable)로 나뉘게 된다. Reference object들을 이용하면 reachable한 객체에 대해서 참조에 대한 강약을 조절할 수 있다.

Reference object는 참조의 강약에 따라 Strong reference, Soft reference, Weak reference, Phantom reference로 나뉘고 강약의 세기는 다음과 같다.

 Strong reference > Soft reference > Weak reference > Phantom reference

여러가지 형태로 객체를 동시에 참조할 수 있는데 이 경우 가장 강한 참조가 객체에 대한 참조의 강약을 결정한다. 예를 들어 하나의 객체에 strong reference와 weak reference가 있다면 이 객체에 대한 참조의 강약은 strong reference에 의해 결정되고 이 경우 강한 참조로 도달할 수 있다(strongly reachable)고 볼 수 있다. 이 경우 만약 strong reference가 사라지게 된다면 이 객체의 reachability는 strongly reachable에서 weakly reachable로 바뀌게 된다.

http://dna.daum.net/wiki/imgs/custom/reachability.gif

Reference queue #

Reference object들의 reachability가 변한 후 garbage collector에 의해 수거될 때 finalize()가 호출된 후 그 reference object는 연관된 reference queue에 쌓이게 된다. 이런 식으로 객체가 소멸되어 가기 전에 queue를 한번 거쳐감으로써 객체 소멸에 필요한 로직을 추가할 수 있게 해준다.

Reference objects #

Strong reference #

Strong reference는 new를 이용하여 객체를 생성하면 생기게 되는 참조를 말한며 reachable하고 strong reference에 의해 참조되고 있는 객체는 garbage collection 대상에서 무조건 제외된다. 때문에 자바가 자동으로 메모리 관리를 해준다고는 하지만 memory leak을 방지하기 위해서는 객체가 strong reference되고 있는지 주의해서 볼 필요가 있다.

  • Strong reference를 사용할 경우 memory leak이 나타날 수 있는 경우에 대한 예제 Memory leak이 나타날 수 있는 대표적인 경우는 class variable(static modifier사용)로 Map과 같은 collection을 사용했을 때이다. 다음과 같은 코드를 보자. 

import java.util.ArrayList;
import java.util.List;

public class StrongReferenceSample {
	private static List<String> stack = new ArrayList<String>();

	private static int position;

	public static void push(String str) {
		stack.add(str);
		position++;
	}

	public static String pop() {
		if (position > 0) {
			// stack.remove(position);
			return stack.get(position--);
		}
		return null;
	}
}

위의 코드는 간단한 String객체를 담을 수 있는 stack을 구현한 것이다. push와 pop 두 가지 기능만을 가지고 있는데 pop() method를 보면 memory leak을 유발할 수 있는 가능성을 내포하고 있다. 다음 그림을 보면 쉽게 이해할 수 있을 것이다.

http://dna.daum.net/wiki/imgs/custom/stack.gif

위의 그림처럼 3개의 데이터를 stack에 넣고(그림1) 그 후 하나의 데이터를 꺼낸 경우<그림2>를 생각해본다면 빨갛게 표시된 3번째 슬롯에서 가리키고 있는 객체는 사용되고 있지 않지만 strong reference가 존재하기 때문에 이 stack에 또 다른 객체를 추가해서 참조를 바꾸거나 명시적으로 참조를 지워주지 않으면 수거되지 않고 계속 살아있게 된다.

Soft reference #

Soft reference는 ''SoftReference''객체에 reference를 넘겨 주어 생성할 수 있다.

SoftReference sr = new SoftReference(new Object());

Soft reference에 의해 참조된 객체는 strong reference와는 다르게 garbage collector에 의해 수거 될 수도 있고 되지 않을 수도 있다. 메모리에 충분히 여유가 있다면 garbage collection이 수행되고 있다 하더라도 softly reachable한 객체는 수거되지 않는다. 하지만 메모리에 여유가 없다면, 좀 더 정확히 말해서 Out of memory 에러를 낼 상황이라면 soft reference에 의해 참조된 객체는 garbage collector에 의해 수거된다.

Weak reference #

Weak reference는 WeakReference객체에 reference를 넘겨주어 생성할 수 있다.

WeakReference sr = new WeakReference(new Object());

Weak reference에 의해 참조된 객체는 garbage collection이 발생하기 전까지는 객체에 대한 참조를 유지하지만 일단 garbage collection이 발생하면 무조건 수거된다. Weak reference가 사라지는 조건은 garbage collection의 실행 주기와 일치하는 것이다. 이를 이용하면 짧은 시간 동안 자주 쓰일 수 있는 객체를 캐쉬할 때 유용하게 이용할 수 있다. 예를 들어 다음과 같은 코드를 보자.

...

	WeakReference<String> wr;

	public String getFileContent(String filename) {
		String fileContent = (wr != null) ? wr.get() : null;  // WeakReference에 의해 파일 내용이 보존되어 있는지 체크.
		if (fileContent == null) {
			fileContent = readFileToString(filename);
			wr = new WeakReference<String>(fileContent); // 글 내용을 WeakReference에 저장.
		}
		return fileContent;
	}

...

위의 코드를 보면 파일에서 글을 읽어 weak reference에 저장하고 그 weak reference의 내용을 캐쉬처럼 재활용하는 것을 볼 수 있다. 만일 garbage collection이 발생하지 않았다면 wr.get() 부분에서 글의 내용이 반환될 것이다. 하지만 garbage collection이 일어났다면 wr.get()은 null을 반환하게 될 것이고 데이터를 다시 채우는 부분을 실행하게 될 것이다.

Phantom reference #

Phantom reference는 finalize()가 호출된 후 그 객체와 관련된 사후 작업을 수행할 필요가 있을 때 사용된다.

Phantom reference의 특이한 점은 다시는 객체는 참조할 수 없다는 것이다. 실제로 phantom reference는 참조되는 객체(referent)를 내부적으로 유지하고 있지만 그 객체를 다시 꺼내오는 get() method에서 무조건 null을 반환하도록 되어 있는데 이는 phantom reference가 참조하는 객체는 다시 활용될 수 없고 다만 garbage collector가 수행되면서 그 객체가 사라질때 관련된 사후 작업만을 할 수 있다는 의미이다. Phantom reference에서 객체를 꺼내게 되면 항상 null이 나오기 때문에 객체가 사라졌다고 생각할 수 있으나 실제로는 사라진 것이 아니고 그렇게 보이는 것일 뿐이다. 그래서 phantom reference는 명시적으로 객체를 소멸시켜주는 clear()를 반드시 호출되어야 한다.

참고: ''PhantomReference.get()''

public class PhantomReference<T> extends Reference<T> {
    ...
    public T get() {
	return null;
    }
}

Reference object의 활용 : simple cache #

Java runtime library에는 이미 weak reference를 이용한 WeakHashMap이 존재하고 garbage collection 시간에 맞춰 자동으로 expire되는 캐쉬로 활용할 수 있다. 이와 비슷한 weak reference를 이용한 캐쉬를 어떻게 구현할 수 있는지 살펴보자.

  • SImpleCache.java 

package andy.ref;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class SimpleCache {
	private Map map = new HashMap();

	public void put(String key, Object value) {
		map.put(key, new WeakReference(value));
	}

	public Object get(String key) {
		Object obj = map.get(key);
		return ((WeakReference) obj).get();
	}
}

간단하게 hash의 value를 ''WeakReference''로 감싸서 넣어봤다. 아래 unit test를 보면 알겠지만 System.gc() 수행 후 hash의 value가 사라지는 것을 볼 수 있다. 일반적으로 캐쉬 프레임웍의경우 캐쉬 엔트리 수를 제한하고 엔트리가 가득찬 경우나 오래된 정보들을 LRU알고리즘등을 써서 어떻게 교체할 것인지에 대한 많은 고민들을 해야한다. 하지만 위와 같이 reference object들을 이용하면 쉽고 간단하게 비슷한 효과를 낼 수 있다.

주의 : 위의 예제에서는 key와 reference object 자체는 strong reference에 계속 유지되고 있으므로 완벽한 memory leak free는 아니지만 reference queue를 이용하면 필요한 뒷 마무리 작업들을 할 수 있을 것이다.

  • SimpleCacheTest.java 

package andy.ref;

import junit.framework.TestCase;

public class SimpleCacheTest extends TestCase {
	public void testCache() {
		String key = new String("Key");
		String value = new String("" + Math.random());

		SimpleCache cache = new SimpleCache();
		cache.put(key, value);

		value = null;

		assertNotNull(cache.get(key));   // Garbage collection 이전에는 value가 존재함.
		System.gc();
		assertNull(cache.get(key));        // value가 사라짐.
	}
}

Trackback 0 and Comment 1