상세 컨텐츠

본문 제목

[Java] Java 메모리 구조, Reflection

😎 지식/자바_스프링_테스트☕

by :부셔져버린개발자 2024. 1. 6. 21:07

본문

Java에서 프로그램을 실행하는 것의 의미

Java 파일을 컴파일러(javac)바이트코드(.class)로 만들고,

이를 ClassLoader가 JVM내로 로딩한다.

로딩된 Class 파일들은 Exceute Engine을 통해 Interpret(해석)된다.

해석된 프로그램은 Runtime Data Area 에 배치되어 실질적인 수행이 이루어지게 된다.


JVM 구조

Java Compiler : JVM 이 해석할 수 있는 Java Byte Code로 변경한다

Java Byte Code : Java Compiler에 의해 수행될 결과물로 .class 파일이다

Class Loader : JVM 내로 .class 파일을 로드하여 Loading 된 클래스들을 Runtime Data Area 에 배치한다

Execution Engine : Loading 된 클래스의 Bytecode를 Interpret(해석) 한다

Runtime Data Area : JVM이라는 프로세스가 프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간

https://inpa.tistory.com/entry/JAVA-%E2%98%95-JVM-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD-%EC%8B%AC%ED%99%94%ED%8E%B8


Runtime Data Area

Method Area : JVM이 동작해서 클래스가 로딩될 때 생성
Stack : 메소드가 호출될 때 할당
Heap : 런타임시 할당

모든 Thread가 공유

1) Heap

new 명령어로 생성된 인스턴스와 객체가 저장되는 구역 (Garbage Collection 담당)

Object, Array 객체 두가지 종류 저장

 

2) Methoad Area

클래스, 변수, Method, Static 변수, 상수 정보 등이 저장되는 영역

 -> runtime constant pool

 

Thread별로 관리

1) PC Register

CPU의 Register와 역할이 비슷함.

현재 수행중인 JVM 명령의 주소값이 저장됨 (각 Thread 별로 하나씩 생성)

 

2) Native Method Stack

다른 언어의 메소드 호출을 위해 할당되는 구역으로 언어에 맞게 Stack이 형성되는 구역


클래스 멤버 변수 초기화 순서

1. static : 클래스가 로드 될 때 변수가 제일 먼저 초기화 된다.

2. field 

3. 생성자 : 객체가 생성될 때, JVM이 내부적으로 Locking (Thread-Safe 영역)

 


가비지 컬렉션 과정에 대해 설명해주세요

GC의 작업을 수행하기 위해 JVM이 어플리케이션의 실행을 잠시 멈추고, GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업을 중단  (Stop The World 과정) 사용하지 않는 메모리를 제거(Mark and Sweep 과정)하고 작업이 재개됩니다.

++ GC의 작업은 Young 영역에 대한 Minor GC와 Old 영역에 대한 Major GC로 구분됩니다.

 


Reflection (리플렉션)

힙 영역에 로드되어 있는 클래스 타입의 객체를 통해

필드/메소드/생성자를 접근 제어자와 상관 없이 사용할 수 있도록 지원하는 API

컴파일 시점이 아닌 런타임 시점 동적으로 특정 클래스의 정보를 추출해낼 수 있음

 

=> 클래스로더를 통해 읽어온 클래스 정보를 사용하는 기술

Class c = Class.forName("클래스이름");
// 메소드
Method[] m = c.getMethods();                     

// 필드
Field[] f = c.getFields();

// 구조체
Constructor[] cs = c.getConstructors();
Class[] inter = c.getInterfaces();
Class superClass = c.getSuperclass();

 

Reflection을 사용해서 스프링에서는 런타임 시에 개발자가 등록한 빈을 애플리케이션에서 가져와 사용할 수 있다


프레임워크 또는 라이브러리 개발시 사용됨

ex) Spring 프레임워크 DI, Serialization/Deserialization 라이브러리

1. 컴포넌트 스캔 (Component Scan)

@Component 어노테이션을 사용하여 클래스를 컴포넌트로 등록한다.

 

컴포넌트 스캔은 스프링이 애플리케이션을 시작할 때 지정된 패키지에서

@Component 가 붙은 클래스를 찾아서 객체를 생성한다.

 

이때 스프링은 리플렉션을 사용하여 클래스의 정보를 조회하고 객체를 생성한다.

 

2. 의존성 주입 (Dependency Injection)

스프링에서는 의존성 주입을 사용하여 객체 간의 의존 관계를 느슨하게 결합합니다.

의존성 주입을 사용하면 객체 간의 의존 관계를 설정하기 위해 직접 코드를 작성할 필요가 없습니다.

스프링은 리플렉션을 사용하여 의존 관계가 필요한 클래스의 생성자를 호출하고 필요한 객체를 주입합니다.

 

3. AOP (Aspect Oriented Programming)

스프링에서는 AOP를 사용하여 애플리케이션의 여러 부분에 공통으로 적용되는 기능을 모듈화한다

AOP는 프록시 객체를 생성하여 핵심 로직을 실행하기 전과 후에 공통으로 수행할 코드를 추가한다

이때 스프링은 리플렉션을 사용하여 프록시 객체를 생성하고 필요한 메소드를 호출한다

728x90

관련글 더보기