먼저 변수는 값 타입과 참조 타입이 있으며 값 타입에는 int, double, char 등이며 참조 타입은 class 등입니다. 값 타입은 스택이라는 영역의 메모리에 저장됩니다. 반면에 참조 타입은 new라는 연산자를 통해서 객체가 생성되면 멤버변수들은 힙이라는 영역의 메모리에 저장되며 이 객체 변수는 힙 영역에 메모리를 가리키는 주소값을 가지며 스택에 저장이 됩니다. 그래서 참조 타입이라고 불립니다. 그리고 .NET에서는 가비지 수집기가 존재하여 C++에서 처럼 delete를 해주지 않아도 시점을 알 수는 없지만 가비지 수집기가 힙 영역에 사용하지 않는 메모리를 정리를 해줍니다. 그렇다면 .NET에서는 메모리에 대해서 개발자는 신경쓰지 않아도 될까요? 정답은 상황에 따라서 다릅니다. 우리가 선언하는 변수를 리소스라고 생각할 때 리소스에는 두 가지가 존재합니다. 바로 관리되는 리소스와 네이티브 리소스입니다. 관리되는 리소스는 사용자가 직접 만든 클래스나 .NET Framework에서 제공하는 클래스입니다. 네이티브 리소스는 파일핸들이나 API를 사용하는 리소스입니다. 이 네이티브 리소스는 힙 외부에 할당된 메모리를 사용하기 때문에 가비지 수집기에서 메모리를 해제할 수 없습니다. 네이티브 리소스를 사용하는 프로그램에서는 이 부분에 대한 메모리를 관리해주어야 메모리 누수가 발생하지 않게 됩니다. 그러면 이러한 리소스들을 정리해주는 IDisposable
public
class
DisposableClass :
IDisposable {
private
SqlConnection
connection;
private
IntPtr
fileHandle;
public
DisposableClass()
{
System.Diagnostics.Debug.WriteLine("생성자입니다.");
}
~DisposableClass()
{
Dispose(false);
System.Diagnostics.Debug.WriteLine("소멸자입니다.");
}
[System.Runtime.InteropServices.DllImport("Kernel32")]
private
extern
static
Boolean
CloseHandle(IntPtr
handle);
public
void
Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
System.Diagnostics.Debug.WriteLine("Dispose()
호출.");
}
protected
virtual
void
Dispose(bool
disposing)
{
if
(disposing)
{
if (connection !=
null)
connection.Dispose();
}
if (fileHandle !=
IntPtr.Zero)
{
CloseHandle(fileHandle);
fileHandle =
IntPtr.Zero;
}
} } |
http://msdn.microsoft.com/ko-kr/magazine/cc163392.aspx
그러면 이제 DisposableClass 클래스를 생성하도록 해보겠습니다.
1번 : using 키워드 미사용 |
DisposableClass disposableClass = new DisposableClass(); |
2번 : using 키워드 사용 |
using (DisposableClass disposableClass = new DisposableClass()) {
… } |
상속받아 구현해주어야 합니다.
여기서 저는 한가지 궁금증이 생겼습니다. SqlConnection과 같이 관리되는 리소스를 using키워드와 함께 객체로 생성하면 변수 connection의 값도 모두 해제되는 것인줄 알았습니다. 하지만 Dispose메소드는 변수 connection의 멤버변수들(리소스)을 해제해주는 것이지 connection의 값(참조주소)이 해제되는 것은 아닙니다. 물론 이 참조값은 int형의 4바이트뿐이 안됩니다. 또한 이 값은 가비지 수집기에 의해서 해제가 됩니다. 가비지 수집기는 어떻게 이 참조값을 해제해주는지 알 수 없지만 가비지 수집기에 명시적으로 이 값을 해제시키는 방법은 있습니다. 바로 connection변수에 null를 넣어주는 것입니다. GC.Collect()란 메소드는 명시적으로 가비지 수집기에게 메모리를 정리하라는 것을 알려줍니다. 만약에 connection변수에 null이란 값을 넣어주고 GC.Collect()를 호출하면 connection변수의 참조값을 바로 해제해줍니다. 실제적으로 코드가 생성되는 것을 한번 살펴보아야 확실히 알 수 있겠지만 제 생각으로는 uisng키워드에서 생성된 객체는 {}에서만 사용할 수 있으며 다른 곳에서는 사용할 수 없는 값이기 때문에 아마 {}안에서 마지막에 null를 대입해주는 것이 아닐까라는 생각이 듭니다.
'GET > FrameWork' 카테고리의 다른 글
방랑이가 생각하는 Spring.NET... (0) | 2009.10.06 |
---|---|
Spring.NET - 레퍼런스 문서 한글화 사이트.. (0) | 2009.09.30 |
Spring 컨테이너와 아키텍처 구성 (0) | 2009.09.30 |
Spring.NET 생명 주기 (0) | 2009.09.30 |
Hands-on Labs for EL 4.1 and Unity 1.2 (0) | 2009.09.29 |