Write Once, Run Anywhere(WORA; 한국어: 작성은 한 번만, 돌리는 건 어디서든)은 1995년에 썬 마이크로시스템즈가 만든 자바의 표어이다. 이는 컴퓨터에 따라 다른 코드를 작성해야 했던 어셈블리어와 다르게 자바는 컴퓨터가 달라도 하나의 통일된 코드로 실행할 수 있다는 장점을 나타내기 위해 제작되었다. 현대에는 자바뿐만 아니라 대부분의 프로그래밍 언어가 이를 일부분에서 모두 지원한다.
자바의 표어를 기억하면서 어떻게 저게 가능할까라는 의문을 가지며 읽으면 좋을거 같습니다.
큰 그림부터 그려보면
JDK ⊃ JRE ⊃ JVM
이런 포함관계를 갖는다는 것을 기억하고 정리해보려고 합니다.
JVM은 자바를 실행하기 위한 가상 기계입니다.
JVM의 등장으로 개발자는
일종의 에뮬레이터이기 때문에 자바 프로그램이 어느 기기, 또는 어느 운영체제 상에서도 실행될 수 있다는 것입니다.
.java➡️자바 컴파일러➡️.class(Java bytecode)➡️JVM : OS가 이해할 수 있도록 해석➡️OS
메모리를 개발자가 직접 관리하지 않아도 됩니다.
JVM은 가바지 컬렉션을 통해 불필요한 메모리를 알아서 정리해줍니다. (C언어를 이용하면 free()라는 함수를 통해서 직접 메모리를 해체해야 합니다.) 즉 동적할당을 프로그래머에게 맡기지 않고 JVM에서 전적으로 맡고 스스로 수행합니다.
JVM은 위와 같이 구성되어져 있는데 하나씩 살펴봅시다.
바이트 코드로 작성된 class파일을 JVM내로 로드하는 역할을 합니다.
class들은 Runtime Data Area에 배치됩니다.
Class Loader에 의해 메모리엑 적재된 클래스의 Bytecode들을 기계어로 변경하고 명령어 단위로 실행합니다.
명령어 실행 방식
Heap 메모리 영역에 생성된 객체들 중에 참조되지 않는 객체들을 탐색 후에 제거하는 역할
JVM의 Heap 영역은 처음에 설계될 때 2가지의 전제로 설계되었다고 합니다.
대부분의 객체는 금방 접근 불가능한 상태가 된다.
오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.
(Perm 영역은 Java8 이후부터 제거되었습니다.)
따라서 객체의 생존기간에 따라 Heap 영역을 Young,Old 2가지로 나누게 되었습니다. 여기서 참조 변수의 개념을 알고가야 합니다. 참조 변수는 객체의 주소가 저장된 변수입니다. 참조 변수는 Stack 영역에 있습니다. 참조변수가 null이 된다면 Heap 영역에 있는 객체는 Unreachable한 상태가 되었다고 표현됩니다. Unreachabel한 객체는 필요없기 때문에 사라지는데 사라지게 만드는 역할을 가비지 컬렉터가 합니다. 다시 돌아와서 Young 영역과 Old영역의 기준을 살펴봅시다.
Young 영역
Old 영역
Young 영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생합니다.
Old 영역에 대한 가비지 컬력션을 Mojor GC 또는 Full GC라고 부릅니다.
Young 영역에 있는 객체를 참조하는 객체가 Old 영역에 존재할 수도 있습니다. 따라서 Young영역에 Minor GC가 실행될 때 Old 영역이 참조하고 있는지 확인을 해야 합니다. 처음부터 끝까지 Old 영역 모두를 확인하는 것이 비효율적이기 때문에 카드 테이블을 조회하여 참조하고 있는지 확인합니다.
즉 카드 테이블에는 Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때마다 그에 대한 정보가 표시됩니다.
메모리의 구조를 생각해봅시다. 프로그램이 실행되기 위해서 먼저 프로그램이 메모리에 로드되어야 합니다. 운영체제로 할당받는 대표적인 메모리 공간을 떠올려보면 각자 어떤 역할을 하는지 더 자세히 눈에 들어옵니다.
실제로 어떻게 메모리가 사용되는지 살펴봅시다.
JVM은 하나의 프로세스입니다. 프로세는 실행중인 프로그램을 프로세스라고 하는데요.
위 그림을 보면 Main Thread가 있습니다,
이는 우리가 코드를 짤 때 사용하는 main()메서드입니다.
하지만 프로그램을 만들때 하나의 Thread만을 이용할 수도 있고 여러 개의 Thread를 사용할 수도 있습니다.
Java 언어로 만들어진 대표적인 프로그램인
톰캣(Web Application Server)의 경우 여러 개의 Thread를 지원하여 사용자의 요청마다 별도의 Thread를 만듭니다. 그러나 요청마다 새로운 Thread를 만드는 것은 비효율적입니다. 왜냐하면 다음 사용자가 사용할 수도 있는데 버리고 다시 만드는 비용이 발생하기 때문입니다. 그래서 Thread Pool을 이용하여 개수를 정해 미리 그 개수만큼 만들어두고 이를 계속 재사용하는 것입니다. 그 개수를 개발자가 정하며 최대 200개까지 정할 수 있습니다.
여러 개의 Thread를 이용하는 멀티쓰레드의 경우 위와 같이 Heap영역과 Method영역을 공유합니다. Heap 영역에는 new 연산자로 생성된 객체가 저장되는데 Thread끼리는 이를 공유하기 때문에 Thread에서 이 값을 변경하지 않도록 주의해야 합니다.
JRE는 자바 클래스 라이브러리, 자바가상머신(JVM), 자바 클래스 로더를 포함하고 있습니다.
클래스 로더와 클래스 라이브러리를 통해 작성한 자바 코드를 라이브러리와 결합한 후 JVM에 넘겨 실행시킵니다. JRE는 그 자체로 특별한 기능을 한다기 보다는 JVM이 원활하게 잘 작동할 수 있도록 환경을 맞춰주는 역할을 합니다.
JDK(Java Develpment Kit)는 자발 개발 키트라는 말로 자바 애플리케이션을 구축하기 위한 핵심 플랫폼 구성요소입니다. 그 중심에는 자바 컴파일러가 있다고 합니다.
JDK를 설치하면 JRE,JVM이 자동으로 설치됩니다.
위 링크를 통해 JDK를 설치했다면 개발자는 Java를 통해 개발할 수 있는 모든 환경이 구축되었습니다.
이제 실제로 JDK를 이용하여 cmd창에서 compile을 진행해보려고 합니다.
제가 작성한 아래의 글을 참고하셔서 환경변수를 설정과 cmd로 컴파일을 진행해보시면 됩니다.
컴파일 이후
클래스 파일들과 외부 라이브러리들을 연결하는 링킹의 작업과 연결된 클래스 및 리소스 파일 묶어주는 패키징, 그리고 기능을 테스트해야 하는 나머지 작업들이 있습니다.
결국 개발자는 컴파일->링킹->패키징->테스트의 과정을 모두 수동으로 해야하며 이 과정을 통해서 하나의 프로그램을 만들 수 있습니다.
이를 빌드라고 합니다.
https://mangkyu.tistory.com/118
https://d2.naver.com/helloworld/1329
https://hyoje420.tistory.com/2
https://m.blog.naver.com/goreng2/221770110714
https://kotlinworld.com/38
https://kimvampa.tistory.com/27
https://velog.io/@kmdngmn/Windows-cmd%EC%97%90%EC%84%9C-%ED%8F%B4%EB%8D%94%EB%A5%BC-jar%ED%8C%8C%EC%9D%BC-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0
2023.06.03 JVM 프로세스와 멀티 스레드와 JDK의 설치~끝까지 Update