[JAVA] 클래스는 언제 로딩될까?🙄

charco·2021년 7월 22일
1

재미코딩

목록 보기
5/10

자바의 정석으로 스터디를 하는 도중 static에 대해 의문이 생겼다.
static 멤버는 클래스가 메모리에 로딩될때 같이 메모리에 올라가는데 그 시점이 언제일까?

출처 https://www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/

사실 번역하면서도 모르는 부분이 많았다.
핵심은 클래스가 사용될때 로드된다고 생각하면 될 것 같다.


"클래스를 로드한다" 는 것은 뭔가?

C/C++ 은 기계 언어로 먼저 컴파일되고 후에 linking 을 필요로 한다.
linking 이란 여러 곳에 있는 소스 파일들을 모아서 실행 가능한 프로그램으로 만드는 것이다. 자바는 안한다. 자바의 linking과 비슷한 과정은 JVM에 로드될때 진행된다.

서로 다른 JVM들은 서로 다른 방법들로 클래스들을 로드하지만 기본적인 룰은 필요할때 클래스들을 로드하는 것이다. 로드된 클래스가 다른 클래스를 필요로 하면 그들도 로드된다. 로딩의 과정은 재귀적이다.


언제, 어떻게 자바 클래스는 로드되나?

자바에서 로딩은 ClassLoader에 의해 처리된다. 아래의 예제는 언제, 어떻게 클래스가 로딩되는지 보여준다.

TestLoader.java

package compiler;
public class TestLoader {
	public static void main(String[] args) {
		System.out.println("test");
	}
}

A.java

package compiler;
public class A {
	public void method(){
		System.out.println("inside of A");
	}
}

이클립스에서의 디렉토리 구조다
-src
--compiler
----A.java
----TestLoader.java

아래의 커맨드를 실행함으로 인해 로드되는 클래스 각각의 정보를 알 수 있다.
-verbose:class 옵션은 그 정보들을 보여준다.

java -verbose:class -classpath /home/ron/workspace/UltimateTest/bin/ compiler.TestLoader

결과

[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain$2 from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain$Key from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/]
test
[Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]

만약 TestLoader.java 를 아래처럼 바꾼다면

package compiler;
public class TestLoader {
	public static void main(String[] args) {
		System.out.println("test");
        // A 클래스의 인스턴스 생성
		A a = new A();
		a.method();
	}
}

그리고 위의 커맨드를 실행한다면 결과는 아래처럼 나올것이다.

[Loaded sun.misc.JavaSecurityProtectionDomainAccess from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain$2 from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.ProtectionDomain$Key from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.security.Principal from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded compiler.TestLoader from file:/home/xiwang/workspace/UltimateTest/bin/]
test
<!-- 바뀐 부분 -->
[Loaded compiler.A from file:/home/xiwang/workspace/UltimateTest/bin/]
inside of A
[Loaded java.lang.Shutdown from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /usr/local/java/jdk1.6.0_34/jre/lib/rt.jar]

A 클래스가 사용될때만 로드되는걸 알 수 있다.

클래스는 이럴때 로드된다

  • 새로운 바이트코드가 실행됐을때 ex) SomeClass f = new SomeClass();
  • 바이트코드가 어떤 클래스에 대한 static 참조를 했을떄 ex) System.out

언제 어떻게 클래스가 초기화될까?

클래스는 클래스 안에있는 symbol(?)이 처음으로 사용됐을때 초기화된다.
클래스가 로드될때 초기화되지는 않는다.

JVM 은 초기화 하기 전에 수퍼클래스와 필드들을 문자순서대로 초기화하고
static, final 필드들을 초기화하고
모든 필드에 대해 기본값을 줄 것이다.

profile
아직 배우는 중입니다

0개의 댓글