수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1691996
  • Today | 140
  • Yesterday | 564

1 Articles, Search for '약한 참조'

  1. 2007/05/18 유연한 참조로 메모리 누수 막기
Programming/Java2007/05/18 11:32

유연한 참조로 메모리 누수 막기

난이도 : 중급

Brian Goetz, Principal Consultant, Quiotix


2006 년 1 월 24 일

지난 달에는 약한 참조(weak references)에 대해 설명했다. 이번 달에는 또 다른 형식의 참조 객체(Reference)인 유연한 참조(soft references)를 설명한다. 이것 역시 메모리 사용을 관리하고 잠재적인 메모리 누수를 없애는 보조 가비지 컬렉터이다.
가비지 컬렉션으로 자바 프로그램은 메모리 누수에 대해 면역성을 갖는다. 적어도 좁은 의미의 "메모리 누수 "의 경우가 그렇다는 것이다. 하지만 자바 프로그램의 객체 수명주기의 문제를 완전히 무시할 수 있다는 의미는 아니다. 자바 프로그램에서의 메모리 누수는 객체의 수명주기에 대한 주의가 부족할 때나 객체 수명 주기를 관리하는 표준 방식들을 파괴했을 때 발생한다. 예를 들어, 지난 시간에는 우리는 객체의 수명주기를 분명히 정하지 못하면, 메타데이터와 일시적인 객체를 제휴하려고 할 때 의도하지 않은 객체 보유를 야기하게 된다는 것을 배웠다. 객체 수명주기 관리를 무시하거나 메모리 누수로 진행될 수 있는 다른 이디엄들도 있다.

객체 로이터링(Object loitering)

메모리 누수의 한 형태인 객체 로이터링은 Listing 1의 LeakyChecksum 클래스가 설명하고 있다. 이것은 getFileChecksum() 메소드를 제공하여 파일 컨텐트의 체크섬을 계산한다. getFileChecksum() 메소드는 파일 내용들을 버퍼로 읽어 들여 체크섬을 계산한다. 보다 단순한 구현은 버퍼를 getFileChecksum() 내의 로컬 변수로 할당하는 것이다. 인스턴스 필드에 버퍼를 캐싱하여 메모리 혼합을 줄인다. 이러한 "최적화 " 로는 부족하다. 객체 할당이 더 낫다. (또한 버퍼를 로컬 변수에서 인스턴스 변수로 승격시키면 추가적인 동기화 없이 더 이상의 쓰레드 보안 없는 클래스로 만든다. 단순한 구현은 getFileChecksum()이 synchronized로 선언될 필요가 없고, 동시에 호출될 때 더 나은 확장성을 제공한다.)


Listing 1. "object loitering" 클래스



이 클래스는 많은 문제들을 갖고 있지만 메모리 누수에 집중해 보자. 버퍼를 캐싱하려는 결정은 이것이 프로그램 내에서 여러 번 호출될 수 있고 재할당 보다는 버퍼를 재사용하는 것이 더 효율적이라는 가정에서 나온 것이다. 하지만 결과적으로 버퍼는 결코 릴리스 되지 않는다. (LeakyChecksum 객체가 가비지 컬렉션이 되지 않는 한) 프로그램을 통해 언제나 접근할 수 있기 때문이다. 더욱 나쁜 것은 이것은 줄어들 수 없기 때문에 LeakyChecksum은 영구적으로 버퍼를 보유하게 된다. 이는 가비지 컬렉터에 많은 부담을 주고 더 많은 컬렉션을 요구한다. 앞으로의 체크섬을 계산할 목적으로 큰 버퍼를 사용한다면 가장 비효율적인 일이 아닐 수 없다.

LeakyChecksum에서 문제의 원인은 버퍼가 논리적으로 getFileChecksum() 연산에만 국한되기 때문이다. 하지만 수명 주기는 인공적으로 늘어나서 인스턴스 필드까지 진입한다. 결과적으로 JVM 대신에 이 클래스가 버퍼의 수명 주기를 관리해야 한다.


유연한 참조(soft reference)

이전 글에서 객체가 프로그램에 의해 사용되는 동안 객체에 접근하는 대안 방식을 약한 참조(weak references)가 제공하는 방법을 배웠다. 하지만 수명은 연장하지 않았다. Reference의 또 다른 하위 클래스인 유연한 참조(soft reference)는 다르면서도 관련된 목표를 수행한다. 약한 참조의 경우 애플리케이션이 가비지 컬렉션을 방해하지 않는 참조를 만들도록 한 반면 유연한 참조에서는 애플리케이션이 몇몇 객체를 "소모 가능한 것 "으로 위임하여 보조 가비지 컬렉터를 모으도록 하고 있다. 애플리케이션이 메모리를 사용하는지의 여부를 파악하는데 가비지 컬렉터가 제 기능을 하기 때문에 가용 메모리의 적절한 사용법을 결정하는 것은 애플리케이션에 달려있다. 애플리케이션이 객체 보유에 대해 그릇된 결정을 내린다면 퍼포먼스가 나빠진다. 왜냐하면 가비지 컬렉터는 애플리케이션이 메모리를 초과하여 실행되는 것을 막아야 하기 때문이다.

캐싱은 일반적인 퍼포먼스 최적화 방법이다. 애플리케이션이 이전 계산의 결과를 재사용 하는 것이 가능하다. 다시 계산을 할 필요가 없다. 캐싱은 CPU 활용과 메모리 사용은 서로 상쇄된다. 이상적인 균형은 얼마나 많은 메모리를 사용할 수 있는가에 달려있다. 너무 적은 캐싱으로는 원하는 퍼포먼스를 얻을 수 없다. 또한, 캐싱이 너무 많으면 퍼포먼스가 타격을 받는다. 너무 많은 메모리가 캐싱에 소비되기 때문에 다른 것에 쓰일 수 있는 것이 충분치 않기 때문이다. 메모리 수요를 결정할 때에는 애플리케이션 보다 가비지 컬렉터가 더 나은 위치에 있기 때문에 이러한 결정을 내릴 때에는 가비지 컬렉터의 도움을 받는 것이 합리적이다. 바로 이것이 유연한 참조가 하는 일이다.

객체에 유일하게 남아있는 참조가 약한 참조이거나 유연한 참조라면 그 객체는 유연하게 접근할 수 있다. 가비지 컬렉터는, 약하게 접근 할 수 있는 객체에 수행하는 것 처럼 이러한 객체들을 공격적으로 모으지 않는다. 대신 메모리가 정말 필요할 경우에만 유연하게 접근할 수 있는 객체를 모은다. 유연한 참조는 가비지 컬렉터에게 "메모리가 그렇게 적지 않다면 이 객체를 보유하고 싶다. 하지만 메모리가 부족하면 계속 진행하여 메모리를 모으면 처리하겠다. "라는 명령하는 방식이라고 할 수 있다. 가비지 컬렉터는 OutOfMemoryError를 던지기 전에 모든 유연한 참조를 제거해야 한다.

캐싱된 버퍼를 관리하는 유연한 참조를 사용하여 LeakyChecksum의 문제를 픽스할 수 있다.(Listing 2). 이제 메모리가 요구되지 않는 한 버퍼가 보유 되지만, 가비지 컬렉터에 의해 사용될 수 있다.


Listing 2. 유연한 참조로 LeakyChecksum 해결하기



캐시

CachingChecksum은 유연한 참조를 사용하여 한 개의 객체를 캐싱하고 JVM이 상세를 핸들하도록 하였다. 이와 비슷하게, GUI 애플리케이션에서 비트맵 그래픽을 캐싱하는데 유연한 참조가 사용된다. 유연한 참조가 사용될 수 있는지의 열쇠는 애플리케이션이 캐싱되는 데이터의 손실에서 회복될 수 있는지에 달려있다.

한 개 이상의 객체를 캐싱해야 한다면 Map을 사용하면 된다. 하지만 유연한 참조를 적용하는 방식에는 선택권이 있다. 캐싱을 Map> 또는 SoftReference>로서 관리할 수 있다. 대게는 후자 옵션이 사용된다. 컬렉터 작업이 수월하고 메모리 수요가 높을 때 전체 캐시를 수월하게 사용할 수 있기 때문이다. 가끔 캐시를 구현할 때 유연한 참조 대신 약한 참조가 사용되지만 이렇게 되면 캐싱 퍼포먼스는 나빠진다. 실제로, 약한 참조는 객체가 약하게 접근 가능한 것으로 된 후에 빠르게 제거될 것이다. 소소한 가비지 컬렉션들은 자주 실행되기 때문이다.

퍼포먼스를 위해 캐싱에 많이 의존하는 애플리케이션의 경우 유연한 참조는 너무 무디다. 유연한 종료, 복사, 트랜잭션 캐싱을 제공하는 보다 고급의 캐싱 프레임웍으로 대체해야 한다는 의미는 아니다. "값싸고 지저분한 " 캐싱 메커니즘으로서는 매력적인 장치이다.

약한 참조와 마찬가지로, 유연한 참조는 제휴 참조 큐를 사용하여 만들어지고, 가비지 컬렉터에 의해 생성될 때 이 참조가 인큐(enqueue)된다. 참조 큐는 약한 참조 만큼 유연한 참조에서는 유용하지 않다. 하지만 적은 메모리에서 애플리케이션이 시작할 때 관리 경고를 만드는데 사용될 수 있다.


가비지 컬렉터가 Reference를 핸들하는 방법

약한 참조와 유연한 참조 모두 (팬텀 참조(phantom references)처럼) 추상 Reference 클래스를 확장한다. 참조 객체들은 가비지 컬렉터에 의해 특별하게 취급된다. 가비지 컬렉터가 힙을 추적하는 과정에서 Reference를 만나면 대상 객체를 마킹 또는 추적하지 않고 대신 알려진 활성 Reference 객체 큐에 그 Reference를 둔다. 트레이싱 후에 컬렉터는 유연하게 참조할 수 있는 객체들을 규명한다. 이러한 객체에는 강한 참조가 존재하지 않지만 유연한 참조는 존재한다. 가비지 컬렉터는 현재 컬렉션에 의해 사용된 메모리 양과 다른 정책 사항에 기반하여 유연한 참조가 이 시점에서 제거되었는지의 여부를 판단한다. 상응하는 참조 큐가 있다면 정리될 유연한 참조가 인큐된다. 남아있는 객체들은 루트 세트로서 취급되고 힙 트레이스는 이러한 루트들을 사용하여 지속되어 유연한 참조를 통해 접근 가능한 객체들이 마킹될 수 있도록 한다.

유연한 참조를 처리한 후에 약하게 접근 할 수 있는 객체 세트가 정의된다. 이 객체에는 강한 참조나 유연한 참조가 존재하지 않는다. 이들은 정리 및 인큐된다. 모든 Reference 유형들은 인큐 되기 전에 정리되어서 사후 클린업을 핸들하는 쓰레드는 대상 객체에 액세스 할 수 없다. 이 같은 이유로 Reference가 참조 큐와 연합하여 사용될 때, WeakHashMap의 Map.Entry가 WeakReference를 확장하는 것 처럼) 적절한 참조 유형을 분류하고 디자인에서 직접 사용하거나 클린업을 필요로 하는 엔터티에 대한 참조를 저장한다.


참조 프로세싱의 퍼포먼스 비용

참조 객체들은 가비지 컬렉션 프로세스에 추가 비용을 부과한다. 각 가비지 컬렉션에서 활성 Reference 객체들의 리스트가 만들어져야 하고 각 참조는 적절하게 처리되어 Reference 당 오버헤드를 각 컬렉션에 추가한다. 이 때 해당 객체가 컬렉팅 되는지의 여부는 상관이 없다. Reference 객체들은 가비지 컬렉션에 속해있고 해당 객체 전에 컬렉팅 될 수 있다. 이 같은 경우는 인큐가 되지 않는 경우이다.


어레이 기반 컬렉션

스택이나 순환식 버퍼 같은 데이터 구조를 구현할 때 어레이가 사용될 때 또 다른 형태의 객체 로이터링이 발생한다. Listing 3의 LeakyStack 클래스는 어레이의 지원을 받는 스택의 구현 모습이다. pop() 메소드에서 상위 포인터가 감소된 후에도 elements는 스택에서 없어진 객체에 대한 참조를 여전히 유지하고 있다. 이 객체에 대한 참조는 프로그램에 의해서도 접근할 수 있다. 그 프로그램이 실제로 그 참조를 다시 사용하지 않더라도 말이다. 이 위치가 push()에 의해 재사용 될 때까지 객체의 가비지 컬렉션을 방지한다.


Listing 3. 어레이 기반 컬렉션에서의 객체 로이터링



이 경우 객체 로이터링에 대한 해결책은 스택에서 제거된 후에 참조를 무효로 하는 것이다. (Listing 3). 하지만 클래스가 자신의 메모리를 관리하는 경우는 매우 드문 상황이다. 더 이상 필요하지 않는 객체를 무효로 하는 것이 좋다. 대부분, 공격적으로 참조를 무효화 하는 것에는 퍼포먼스나 메모리 사용에 있어서 이득이 없다. 형편 없는 퍼포먼스나 NullPointerException을 발생시킬 뿐이다. 이러한 알고리즘의 연결된 구현은 문제가 없다. 연결된 구현에서 링크 노드의 수명(그리고 저장될 객체에 대한 참조)은 객체가 컬렉션에 저장되는 동안 자동으로 묶인다. 약한 참조는 이 문제를 해결하는데 사용된다. 강한 참조 대신에 약한 참조 어레이를 관리한다. 하지만 실제로 LeakyStack는 자신의 메모리를 관리하고 더 이상 필요 없는 객체에 대한 참조가 제거되도록 한다. 어레이를 사용하여 스택이나 버퍼를 구현하는 것은 할당을 줄이는 최적화이지만 구현자에게는 큰 짐이다. 이 어레이에 저장된 참조들의 수명을 관리해야 하기 때문이다.


요약

약한 참조와 마찬가지로 유연한 참조는 애플리케이션에서 객체 로이터링을 방지한다. 애플리케이션이 유연하게 참조된 객체의 손실을 감당할 수 있다면 유연한 참조가 알맞다.

기사의 원문보기

Java theory and practice: Plugging memory leaks with soft references
http://www.ibm.com/developerworks/java/ ··· 246.html



참고자료

교육

"Java theory and practice: 메모리 누수와 약한 참조"
http://www-128.ibm.com/developerworks/k ··· dex.html

"Tuning garbage collection in the HotSpot JVM"
http://www.ibm.com/developerworks/java/ ··· 06304%2F

Reference objects and garbage collection
http://java.sun.com/developer/technical ··· efobj%2F

Java theory and practice
http://www.ibm.com/developerworks/views ··· ctice%3A

The Java technology zone
http://www.ibm.com/developerworks/java/

제품 및 기술 얻기

JTune

http://www.hp.com/products1/unix/java/java2/hpjtune/
"Java" 카테고리의 다른 글
  • 웹2.0(Ajax)과 아키텍처의 구현 (0)2007/05/18
  • 리팩토링을 이용한 자바 성능 최적화 기법 (0)2007/05/18
  • 유연한 참조로 메모리 누수 막기 (0)2007/05/18
  • EJB 기반 프로젝트 수행 가이드 ④ (0)2007/05/18
  • EJB 기반 프로젝트 수행 가이드 ③ (0)2007/05/18
2007/05/18 11:32 2007/05/18 11:32
Posted by webdizen
Tags Java, 메모리 누수, 약한 참조
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/2997

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • 리눅스 커널
  • Blogging
  • free
  • SNMP
  • Top N
  • CRLF
  • 화장품
  • 임페리얼 클래식
  • 로깅
  • 게임
  • vim
  • Photograph
  • 데이터 프로파일링
  • Visual Studio 2005
  • 미디어
  • 유저 정보
  • OLAP 큐브
  • GIF
  • 까무스
  • Web

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 학교 과제물중 쓰레드에 대하....
    장진혁 03/17
  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • Lots of students know techn....
    Bobbi35Shannon 02/25
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  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      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Rodman®
      • ■ Feel So Good~! ■
      • 까만 나비
      • 나를 가꾸는 시간.
      • 나만의 즐거움~~!
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.