개발자가 포인터에 임의로 메모리 주소를 저장할 수 있다.
반대로 참조(reference) 자료형은 메모리 주소를 직접 조작하지 못한다.
참조 자료형은 변수를 생성할 때 heap 영역에 메모리를 할당하고, 할당된 메모리에 데이터를 저장하고, 해당 메모리의 주소를 변수에 저장하는 과정이 자동으로 이루어진다.
포인터는 개발자가 메모리 주소를 직접 조작할 수 있다.
따라서 만약에 포인터에 잘못된 주소를 저장할 수도 있으며
이 경우 segment fault 와 같은 오류가 발생할 수도 있다.
바로 JVM(Java Virtual Machine)과 GC(Garbage Collector)에 있다.
객체는 생성 시 heap 영역에 저장되고 참조 변수는 stack 영역에 선언되고 객체의 heap 주소를 변수에 저장한다.
이때 heap 메모리가 꽉 차게 되면 Garbage Collector은 더 이상 stack에서 참조되지 않은 heap 영역의 객체들을 제거하고 이 과정에서 GC에 의해 제거되지 않은 다른 객체들도 heap 메모리의 다른 영역으로 이동한다.
즉 heap 영역에서 객체의 주소는 고정적이지 않다.
GC가 객체를 제거하면, 제거된 객체의 메모리 공간은 빈 공간이 되고, 이 빈 공간들이 흩어져서 단편화가 발생한다.
이렇게 단편화된 메모리 공간을 효율적으로 사용하기 위해, GC는 객체들을 이동시키거나 메모리 공간을 조작하여 단편화를 해소한다.
이때, 다른 객체들이 메모리 공간을 이동하게 되어, 객체들의 메모리 주소가 변경될 수 있다.
만약 자바가 포인터를 허용한다면
개발자는 Garbage Collector에 의해 주소값이 바뀌어도 이를 알지 못하고 기존의 주소값으로 접근을 시도하여 개발자가 의도하지 주소에 접근할 수도 있다.
포인터는 개발자가 임의로 메모리 값을 설정하고 해당 메모리에 직접 접근이 가능하다.
따라서 참조 자료형보다는 메모리 설정 자율성이 높다.
자바는 GC를 이용하여 개발자 대신 참조되지 않은 메모리는 자동으로 해제하여 메모리를 효율적으로 관리한다.
포인터는 개발자가 임의의 메모리를 설정할 수 있기에 그에 따라 잘못된 메모리에 접근하여 segment fault오류가 발생할 수 있다.
하지만 자바는 JVM과 GC를 통해 스스로 메모리를 관리하고 개발자가 직접적으로 메모리에 접근하는 것을 막아 이러한 오류를 방지한다.
자바의 JVM, GC가 편리하기는 하지만 이것 자체가 리소스를 낭비하기 때문에 성능상으로는 포인터를 사용하는 게 더 우세하다.
이러한 이유로 극한의 성능을 발휘해야하는 곳에서는 자바보다 C언어를 사용한다고 한다.