🤔내부클래스를 static으로 선언하지 않는다면 메모리 누수가 발생하게 됩니다.
자바에서는 가비지 컬렉터(gc)가 알아서 사용하지 않는 객체를 정리해주는데 이때 사용하지 않는 객체란 다른 곳에서 해당 객체를 참조하지 않는 객체를 의미합니다.(Unreachable한 객체)코드로 확인해보겠습니다.
public class Outer {
int[] data;
public Outer(int size) {
data = new int[size];
}
class Inner {
}
Inner getInnerObject() {
return new Inner();
}
}
🫠Outer class 작성 후 안에 Inner Class를 작성해주었습니다.
이제 힙 사용량을 출력하여 제대로 gc가 작동하고 있는지 확인해보겠습니다.
class GarbageTest {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(() -> {
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
System.out.printf("memory : %d\n", heapMemoryUsage.getUsed());
list.add(new Outer(100000000).getInnerObject());
},0,1000, TimeUnit.MILLISECONDS);
}
}
🥳
MemoryMXBean
를 통해 실제 힙 사용량을 출력할 수 있습니다.
ScheduledExecutorService
를 통해 일정 주기마다 객체를 생성해주면서 힙 사용량을 출력해주었습니다.이제 결과를 보겠습니다.
😥보시면 메모리가 계속해서 증가하는 것을 볼 수 있습니다.
Outer Class의 경우 쓰지 않기에 gc가 작동한다면 메모리가 일정하게 나와야 하는데 위와 같은 결과가 나온 것을 보면 문제가 있는 것을 알 수 있습니다.
gc가 제대로 작동하지 않은 것일 수도 있기에 gc를 강제로 실행시켜보겠습니다.
System.gc()
추가
😰위와 같은 결과가 나온것을 볼 수 있습니다.
gc를 작동시켰지만 같은 결과가 나온 것을 보면 gc가 해당 outer class를 없애지 못했다는 것을 알 수 있습니다. 그러면 이제 내부 클래스를 static으로 선언하고 진행해보겠습니다.
public class Outer {
Object[] data;
public Outer(int size) {
data = new Object[size];
}
static class Inner { <----static 추가
}
Inner getInnerObject() {
return new Inner();
}
}
🥳이제는 gc가 제대로 동작하는 것을 확인 할 수 있습니다.
static추가 전에는 inner class가 outer class를 보고?있기에 gc가 outer class를 지우지 못하는 상황이였습니다. 그러나 static을 추가할 경우 이제는 gc가 제대로 작동하는데 쉽게 생각해서 static을 붙이면 outer class와 같은 효과를 지니고 있다고 생각하시면 됩니다.
😎특별한 경우가 아니라면 내부 클래스는 static으로 선언하시면 될 것 같습니다.
티스토리 인파 - 자바의-내부-클래스는-static-으로-선언하자
토비의 스프링 - 자바의 내부 클래스는 스프링 빈이 될 수 있을까?
이런 유용한 정보를 나눠주셔서 감사합니다.