자바 런타임 환경에서 class를 동적으로 불러와 처리해야하는 경우가 있다.
런타임 환경에서 클래스의 정보에 접근할 수 있게 해주는 자바 기법을 Reflection API 라고 부른다.
자세히 설명하기 전 대표적으로 어디에 사용하는지 예시부터 보자.
@Component
public class RestTemplateConfig {
~~
}
@Component
public class WebService {
private RestTemplateConfig restTemplate;
@Autowired
public WebService(RestTemplateConfig restTemplate){
this.restTemplate = restTemplate;
}
}
Spring 개발을 한번이라도 사용한 사람이라면 의존성 주입을 해봤을거다.
의존성 주입할때 어떻게 리플렉션이 사용되는지 보자.
스프링은 클래스에서 @Autowired가 붙은 생성자나 필드를 확인, 리플렉션을 통해 클래스의 생성자를 검사한 뒤, 생성자에 @Autowired가 붙어 있는지 확인
스프링은 리플렉션을 통해 클래스 생성자의 파라미터 타입을 확인
스프링은 등록된 빈 목록에서 적절한 빈 찾기
리플렉션으로 객체 생성 및 주입
1.
@Autowired
public webService(RestTemplateConfig restTemplate){...}
2.
//우리가 원하는 생성자는 RestTemplateConfig 객체를 Parameter로 받는 생성자이기 때문에
//RestTemplateConfigclass를 넘겨준다
Constructor<?> constructor = WebService.class.getConstructor(RestTemplateConfig.class);
3.
RestTemplateConfig restTemplateConfig = (RestTemplateConfig) applicationContext.getBean(RestTemplateConfig.class);
4.
//이 과정에서 리플렉션을 사용해 WebService 인스턴스를 생성하고, 의존성을 주입
WebService webService = constructor.newInstance(restTemplateConfig);
객체를 Json으로 직렬화하거나 Json을 객체로 역직렬화 할때 사용하는 Jakson 라이브러리 (예
@Setter
@Getter
@AllArgsConstructor
public class User {
private String name;
private int age;
}
public class DeserializationExample {
public static void main(String[] args) {
try {
// JSON 문자열
String jsonString = "{\"name\":\"Lim\", \"age\":31}";
// ObjectMapper를 사용해 JSON 문자열을 User 객체로 역직렬화
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(jsonString, User.class);
// 결과 출력
System.out.println("Name: " + user.getName());
System.out.println("Age: " + user.getAge());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ReflectionExample{
// User 클래스 객체 생성
User user = User.class.getDeclaredConstructor().newInstance();
// 리플렉션을 통해 필드에 값 주입
Field nameField = User.class.getDeclaredField("name");
nameField.setAccessible(true); // private 필드에 접근 허용
nameField.set(user, name);
Field ageField = User.class.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(user, age);
}
이런식으로 알게 모르게 우리는 리플렉션을 많이 사용하고 있었다.
위의 예처럼 런타임에서 동적으로 클래스의 정보를 가져와 사용할 수 있는 이유는 Class 클래스 객체가 존재 하기 때문이다. 클래스명이 Class인 것이다

'Class' 클래스의 동작 원리
자바 프로그래밍이 실행되면 javac 컴파일을 통해 .java -> .class(JVM에서 읽을 수 있는 바이트 코드) 생성 후 Class Loading을 통해 메모리에 로드 한다.클래스가 메모리에 로드되면, JVM은 해당 클래스에 대한 Class 객체를 생성, 이 Class 객체는 클래스의 모든 메타데이터(예: 메서드, 필드, 생성자, 상속 관계 등)를 포함하고 있다.

Java 8에서 도입된 Metaspace는 클래스 메타데이터를 저장하는 영역이다. 이는 Java 7 이전의 PermGen을 대체한 공간이다.
텍스트크기 조정: 메타스페이스는 PermGen과 달리 크기가 고정되지 않으며, 운영 체제의 가용 메모리를 사용해 필요에 따라 확장할 수 있다. 기본 크기 제한이 없기 때문에 메모리 부족 문제가 발생할 가능성이 줄어든다.
내용: 클래스의 메타데이터, 메서드 정보, 상수 풀, 클래스의 구조 정보 등이 저장. 이곳에 저장된 클래스 메타데이터는 클래스가 언로드될 때까지 유지.