Spring
Deep Dive
JVM

JVM이란?

Java Virtual Machine의 약자로, 자바 바이트 코드를 실행할 수 잇는 주체이다.

자바 바이트 코드

운영체제에 독립적이며 모든 JVM 구격에 정의된 대로 자바 바이트 코드를 실행한다.
자바 바이트 코드의 확장자는 .class 입니다.

JVM의 구조와 동작

JAVA 소스 코드 파일 -> 컴파일러 -> 자바 바이트 코드 파일 -> 클래스 로더 -> JVM RUNTIME DATA AREA -> Interpreter or JIT Compiler

Method Area

class의 정보 (클래스 이름, 부모 클래스 이름, 메소드, 변수)를 저장한다. Method Area에 접근하기 위한 방법으로는 Java Reflection이 있다고 할 수 있다.

Java Reflection이란?

런타임에 클래스와 인터페이스 등을 검사하고 조작할 수 있는 기능을 뜻한다.
좀 더 풀어서 설명하자면,
프로그램 실행 중사용자와 운영체제 및 기타 프로그램과 상호작용 하면서 클래스와 인터페이스 등을 검사하고 조작할 수 있는 기능이다.

좀 더 자세히 설명하자면, Runtime에 Method Area에 로딩된 클래스들의 메타데이터를 통해 클래스의 정보를 분석하고, 객체를 생성하고, 생성된 객체를 통해 메소드를 호출하고, 필드에 접근하는 등의 기능을 말한다.

Reflection 사용법

Method Area를 사용하기 위해서 Class Type을 사용해줄 수 있다.

public class ClassExample {
  public static void main(String[] args) throws ClassNotFoundException {
    final Class<MyClass> class1 = MyClass.class;
 
    final MyClass obj = new MyClass();
    final Class<? extends MyClass> class2 = obj.getClass();
 
    final Class<?> class3 = Class.forName("MyClass");
  }
}
class MyClass { }

Class Type에서

  1. getDeclaredField()를 통해서 Field 값을 추출 해낸다.
  2. get( Class Instance )를 통해서 value에 접근할 수 있는데 지금 위의 상황에선 에러가 발생한다.
  • MyClass의 name Filed가 private이기 때문
public class ClassExample {
  public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
    final Class<MyClass> class1 = MyClass.class;
 
    // NoSuchFieldException 발생 가능
    final Field declaredField = class1.getDeclaredField("name");
    declaredField.setAccessible(true);
 
    final MyClass myClass = new MyClass();
    // IllegalAccesssException 발생 가능
    final String name = (String) declaredField.get(myClass);
 
    System.out.println(name);
  }
}
 
class MyClass {
  private final String name = "헐크";
}
  1. 이 때 위와 같이 declaredField에 setAccessible(true)를 설정해주면 값에 접근할 수 있다.

Reflection 사용용도

리플렉션 API의 대표적인 사용 예시로 스프링 프레임워크가 있다. 스프링의 IoC 컨테이너에서 빈(Bean) 객체를 생성하고, 의존성 주입(Dependency Injection)을 처리하는 데 사용된다. 런타임 시에 동적으로 클래스를 로딩하고 객체를 생성하여 의존성을 주입하는 방식을 사용된다.

또한, 자바 직렬화(Serialization)에서도 리플렉션 API가 사용된다. 직렬화란 객체를 바이트 스트림으로 변환하여 저장하거나 네트워크를 통해 전송할 수 있는 방법입니다. 이 때, 리플렉션 API를 사용하여 객체의 정보를 분석하고 바이트 스트림으로 변환하는 작업을 수행한다.

Reflection 사용시 단점

Reference

https://velog.io/@dyunge_100/JAVA-JVM%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC (opens in a new tab)
https://sh970901.tistory.com/120 (opens in a new tab)
우테코 헙크의 자바 (opens in a new tab)