Hi

얕은 복사, 깊은 복사, 참조 계수(Reference Counting) 본문

Programming/Java

얕은 복사, 깊은 복사, 참조 계수(Reference Counting)

SharingWorld 2018. 3. 30. 13:52

 a : Data

 b = a // copy


 복사 정책 2가지

 1. 레퍼런스 복사(얕은 복사)

  * 장점: 속도가 빠르고, 메모리도 덜 쓴다.

  * 단점: 객체의 파괴 시점을 결정할 수 없다.

       => 댕글링 포인터

 해결방법: 참조 계수에 의한 객체 수명 관리



2. 값 복사(깊은 복사)

 * 장점: 객체의 파괴 시점을 결정할 필요가 없다.

 * 단점: 데이터의 크기가 클 수록 속도가 느려지고,

    그만큼의 메모리도 소모해야 한다.


 Reference Counting

 => 참조 계수


 객체의 생성과 소멸

 => StringBuilder - 문자열이 수정될 때마다 객체의 생성을 만드는 것을 방지

      Integer.valueOf - 같은 숫자는 객체를 생성하지 않고 참조할 수 있도록 한다.



 3. 참조 계수 관리하는 2가지 방법

   1. GC : Java, Go, C#, Javascript

     => '런타임(dynamic, virtual)'에 별도의 프로그램이 객체의 수거를 담당한다.

 장점: 런타임에 GC가 판단해서,수거하므로 유연하게 동작한다.

 단점: GC가 발생하면, 프로그램의 성능이 저하된다.

   2. ARC : Objective-C, Swift

 => '컴파일 타임'(static)에 객체의 참조 계수를 관리하는

              코드를 삽입한다.

 장점: 빠르게 동작한다.

 단점: 제대로 된 코드를 작성하지 않으면,

  정상적으로 객체의 메모리가 수거되지 않는다.



 GC가 수거하는 대상

 => 참조 계수가 0인 객체


 참조 계수를 사용했을 때 메모리 누수가 발생할 수 있다.

 => 순환 참조에서 발생한다.


 자원(Resource)

 메모리 자원: 객체 - 참조 계수 - GC

 비메모리 자원? (File 등)

 : 비메모리 자원은 반드시 명시적인 종료 메소드를 통해 해지해주어야 한다.



스택을 만들어보자
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

// 객체가 GC에 의해서 수거되는 시점에 호출되는 메소드 - finalize
class Image {
	byte[] data = new byte[1024 * 1024]; // 4M

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		System.out.println("이미지 파괴");
	}
}

class Node {
	int data;
	Node next;

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		System.out.println("Node finalized");
	}
}


public class Program_0322 {
	public static void foo() {
		Node a = new Node();
		Node b = new Node();

		a.next = b; // 순환참조
		b.next = a;
	}

/*
public static void main(String[] args) throws Exception {
	foo();
	System.gc();
	TimeUnit.SECONDS.sleep(1000);
}
*/

// 강한 참조(Strong Reference)
// : GC의 수거 대상이 되지 않는다.
// 가용한 메모리가 없을 경우, Out Of Memory가 발생한다.

// 약한 참조
// 1. SoftReference
// => Out of Memory에 가까워질 경우 수거 되는 대상.
// 2. WeakReference
// => GC가 발생하면 수거된다.

public static void main(String[] args) throws InterruptedException {
// ArrayList<Image> images = new ArrayList<>();
	ArrayList<WeakReference<Image>> images = new ArrayList<>();
	for (int i = 0 ; i < 1000000000 ; ++i) {
		images.add(new WeakReference<>(new Image()));
		TimeUnit.MICROSECONDS.sleep(1000);
	}
}
/*
public static void main(String[] args) {
	// 1. 객체가 생성되면, 참조 계수는 1이다.
	Image image1 = new Image();

	// 2. 객체 참조가 복사되면, 참조 계수는 증가한다.
	Image image2 = image1;

	// 3. 객체 참조가 사라지면, 객체는 파괴된다.
	image1 = null; // refCount: 1
	image2 = null; // refCount: 0

	// 4. GC를 무조건 실행하는 것이 아니다.
	// System.gc();
	System.out.println("Program end");
}
*/
}

'Programming > Java' 카테고리의 다른 글

hashCode / equals  (0) 2018.04.02
Reflection  (0) 2018.04.02
Exception(예외)와 try-with-resources  (0) 2018.03.29
vi & 터미널(terminal) 명령어  (0) 2018.03.29
비메모리 자원이 있는 객체와 Try with Resources  (0) 2018.03.29