Back

~$1.class

자바 프로젝트 빌드한 것을 전체적으로 압축하여 배포하는 곳에 풀어 반영하지 않고, class 파일만 따로 업로드를 진행했다.
그런데, 이상하게 ~$1.class라는 class 파일이 추가적으로 존재했었다.

당시 ide를 켜놓고 있어서 추측으로 뭔가 ide가 생성한 캐시 파일 같은 것으로 생각하고 같이 반영하지 않았다.
그런데, 서버의 실행에서 ~$1.class 파일이 없다는 오류를 만났다.
일단 급하게 업로드하지 않았던 저 ~$1.class 파일을 같이 반영하고 실행하니 정상적으로 작동했다.

그리고 저 ~$1.class 파일에 대해 찾아봤다.
내부 익명 클래스가 있는 경우 저런 파일이 생성된다고 한다.
실제로 내부 클래스가 있는 다른 빌드된 클래스들을 확인하니 익명이 아닌 경우에는 숫자 1이 붙지 않고 해당 클래스의 이름에 $ 기호가 같이 붙어있는 것들을 확인했다.

기억을 더듬어보니 전에도 경험했던 것이다.
그저 익명의 내부클래스일 경우 이를 숫자로 표현해주는 것일 뿐이었다.

그런데 의문이 생겼다. 내가 직전에 업로드한 클래스는 내부클래스가 전혀 없었다. 클래스 하나에 필드와 메소드밖에 존재하지 않았다.

안에있는 메소드 이것저것 하나씩 지워가면서 빌드를 해보다가, 그냥 저 생성된 class 파일을 디컴파일하여 도대체 뭐가 있는지 확인을 해봤다.

확인을 해보니 내부에는 HashMap을 상속받은 클래스며 this.put으로 몇가지의 내용을 채우는 간단한 내용이 있었다.

import java.util.HashMap;

class 클래스명$1 extends HashMap<Object, Object> {
  {
    this.put("key1", value1);
    this.put("key1", value2);
  }
}

잠시 이게 뭐지 싶다가 이 this.put을 통해 생성하는 key값을 보니 내가 직접 지정한 이름이 적혀있었는데, 이를 통해 이것이 어디에서 왔는지 바로 알게 되었다.

내가 작성한 코드에는 다음과 같은 것이 있었다.

new HashMap<Object, Object>() {
	{
		put("key1", value1);
		put("key2", value2);
	}
}

위와 같이 맨바닥에 작성한 것은 아니고, 이를 메소드의 인자에 넣어서 사용했다.

왜냐하면, 어떤 메소드에 HashMap 타입으로 전달해야 할 인자를 new를 통해 새롭게 선언하고, put 메소드를 통해 원하는 값들을 넣어주고, 선언한 변수명을 가지고 인자로 전달하는 과정 자체가 귀찮아서 그랬다.

그런데, 이를 메소드를 호출하는 그 자리에서 직접 익명으로 생성하여 전달하게 작성했던 것이 문제였다.

예전에 이것에 대해 검색을 했었을 때 stackoverflow 메모리를 낭비하는 경우가 존재하여 권장하지 않는다는 것을 확인한 적이 있다.

다시 찾은 링크 : How to directly initialize a HashMap (in a literal way)?

당시에는 내가 체감되는 성능의 저하도 없었으며, 이게 왜 문제가 되는 것인지도 잘 몰랐으나, 지금은 일단 빌드되는 파일 자체가 여러 개 생기는 것이 마음에 들지 않기 때문에 앞으로는 이렇게 사용하지 말아야겠다고 느꼈다.

귀찮더라도 자바에서 저것은 정석의 방법으로 진행해야겠다.