SlideShare a Scribd company logo
IBM Software Group
IT Medical Center, JADECROSS
© Copyright JADECROSS 2023
jadecross 정환열 이사
2023
JVM 아키텍처 이해를 통한 자바시스템 트러블슈팅
coordinatorj@jadecross.com
목 차
실습 환경설정
하드웨어 및 운영체제 리뷰
Java Virtual Machine
Runtime Data Areas(JVM Memory)
Process Synchronization(Operating System)
Thread Synchronization
JAVA 성능분석 도구
Garbage Collection
실습 환경설정
4
 실습파일 다운로드
 https://www.dropbox.com/s/znp9247yjl11d7w/jadeedu_jvm_20211103.zip?dl=0
 jadeedu_jvm.zip 파일을 C: 하위에 압축 해제
실습 환경설정 (1/8) - 실습파일 다운로드 및 압축 해제
실습 환경설정
jadeedu_jvm_20211103.zip
5
실습 환경설정 (2/8) - VirtualBox 설치
 VirtualBox 6 설치
 C:jadeedu_jvmswVirtualBox-6.1.16-140961-Win.exe 더블클릭
 VirtualBox 환경 설정
 파일  환경설정
실습 환경설정
입력 확장
가상 머신
┗▶ 호스트 키 조합
확장 패키지 추가
Ctrl + Alt
C:jadeedu_jvmswOracle_VM_
VirtualBox_Extension_Pack-
6.1.16.vbox-extpack 선택
6
실습 환경설정 (3/8) - VirtualBox 환경설정
 네트워크 설정
 “Tools  네트워크” 선택
 IP 대역 설정
 192.168.56.0/24 대역으로 네트워크 설정
실습 환경설정
192.168.56.1/24 192.168.56.1/24
192.168.56.1
192.168.56.100
192.168.56.101
192.168.56.254
7
 “NAT 네트워크” 추가
 파일  환경 설정  네트워크“ 
 NAT 네트워크 정보
 네트워크 이름 : EduNatNetwork
 네트워크 CIDR : 192.168.55.0/24
실습 환경설정 (4/8) - VirtualBox 환경설정
실습 환경설정
8
실습 환경설정 (5/8) - 실습 VM 가져오기 및 실행
 버튼 클릭하여 VM 가져오기
 jvmedu 가상머신 실행
실습 환경설정
계정 : root
암호 : edu
“C:jadeedu_jvmvmjvmedujvmedu.vbox”
파일 선택
jvmedu.vbox
jvmedu.vbox
9
실습 환경설정 (6/8) - 원격 접속
 MobaXterm 실행
 jvmedu VM 원격 접속
 192.168.56.96
실습 환경설정
10
실습 환경설정 (7/8)
 실습 환경 최소 조건
 Windows 10, 8G RAM, VirtualBox(하이퍼바이저) 실행 가능해야 함
 SSD 디스크 사용할수록 실습이 용이함
 최소 VM 자원 설정
 vCPU : 4 Core
 Memory : 4 GB
실습 환경설정
VirtualBox(Win 10)
jvmedu
(192.168.56.96)
internet
7080
9080
11
실습 환경설정 (8/8)
 JAVA_HOME 환경변수 설정
실습 환경설정
C:jadeedu_jvmswjava_tooljdk1.8.0_281
 PATH 환경 변수 설정
 java.exe가 실행되도록 PATH 환경변수에 %JAVA_HOME%bin 설정
하드웨어 및 운영체제 리뷰
13
요즘 초등학교에서는?
하드웨어 및 운영체제 리뷰
https://www.youtube.com/watch?v=AkFi90lZmXA&feature=youtu.be
14
컴퓨터 시스템 아키텍쳐
하드웨어 및 운영체제 리뷰
Memory
CPU
Disk
Controller
USB
Controller
Graphic
Adappter
15
FETCH, DECODE, EXECUTE
하드웨어 및 운영체제 리뷰
https://www.youtube.com/watch?v=Z5JC9Ve1sfI&feature=youtu.be
https://www.youtube.com/watch?v=04UGopESS6A&feature=youtu.be
(프로그램 내장 방식)
https://youtu.be/389itBs7YlE?t=717
16
메모리 계층 구조
하드웨어 및 운영체제 리뷰
https://ko.wikipedia.org/wiki/%EC%A7%90_%EA%B7%B8%EB%A0%88%EC%9D%B4
속도
가격
17
프로그램 = 실행 파일 + 라이브러리
 C 실행파일의 빌드 절차
하드웨어 및 운영체제 리뷰
hello.c
(소스 파일)
hello.i
(전처리된 소스파일)
hello.o
(목적 파일)
a.out
(실행 파일)
hello.s
(어셈블리 파일)
C 전처리
C 전처리기
cpp
C 컴파일
C 컴파일러
cc1
어셈블
어셈블러
as
링킹
링커
ld,collect2
사용자 작성
라이브러리
시스템 내장
라이브러리
18
프로그램 -vs- 프로세스
 프로그램
 컴파일, 링크 과정을 거쳐 실행할 수 있는 머신코드로 디스크에 저장되어 있음
 가상메모리를 사용하는 범용 OS에서는 프로그램의 코드 및 변수의 주소가 이미 결정되어짐
 ELF (Executable and Linkable Format)
 리눅스의 오브젝트 파일 형식 (원도우즈에서는 PE(Portable Executable) 사용)
 https://ko.wikipedia.org/wiki/ELF_파일_형식
 프로세스
 실행중인 프로그램
하드웨어 및 운영체제 리뷰
Run-Time
19
LAB) C 프로그램 빌드, 실행, 메모리 레이아웃 이해 (1/3)
 Static Allocation -vs- Dynamic Allocation
하드웨어 및 운영체제 리뷰
cprog.c
#include <stdio.h>
#include <stdlib.h>
int f2(int x);
int a = 10;
int a2 = 20;
int b;
int b2;
int f1(int x) {
return ++x;
}
int main() {
int c = 100, c2;
char *d = "hello";
char *name;
int *score;
name = malloc(50);
score = malloc(20 * sizeof(int));
printf("%sn", d);
printf("addr(TEXT) => main:%p, f1:%p, f2:%pn", main, f1, f2);
printf("addr(CONST) => d:%pn", d);
printf("addr(DATA) => a:%p, a2:%pn", &a, &a2);
printf("addr(BSS) => b:%p, b2:%pn", &b, &b2);
printf("addr(STACK) => c:%p, c2:%pn", &c, &c2);
printf("addr(HEAP) => name:%p, score:%pn", name, score);
return 0;
}
int f2(int x) {
return --x;
}
프로그램
(HDD)
코드/상수
Static
Allocation
TEXT
초기화된 전역변수와 정적변수 DATA
초기화되지 않은 전역변수와 정적변수 BSS
프로세스
(RAM)
코드/상수
Static
Allocation
TEXT
초기화된 전역변수와 정적변수 DATA
초기화되지 않은 전역변수와 정적변수
(0으로 자동 초기화) BSS
동적 할당 메모리
(포인터로 접근)
Dynamic
Allocation
HEAP
지역변수
함수 인자와 리턴 값 STACK
실행
20
LAB) C 프로그램 빌드, 실행, 메모리 레이아웃 이해 (2/3)
 C 프로그램 빌드 및 주소 확인
하드웨어 및 운영체제 리뷰
 C 언어 소스를 빌드하여 실행파일 생성
[root@jvmedu ~]# cd ~/lab/cprogram
[root@jvmedu cprogram]# gcc cprog.c
[root@jvmedu cprogram]# ls -l
total 16
-rwxr-xr-x 1 root root 8624 Oct 18 14:12 a.out
-rw-r--r-- 1 root root 689 Oct 18 14:10 cprog.c
 빌드된 실행파일의 형식을 확인
[root@jvmedu cprogram]# file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs),
for GNU/Linux 2.6.32, BuildID[sha1]=d97dd1cd5b319eb15e2d7fe252100ad309f8c1b7, not stripped
 a.out 실행파일의 변수 및 함수의 주소를 확인
[root@jvmedu cprogram]# readelf -a a.out  또는 nm a.out 으로 주소 확인
Section Headers:
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040 0000000000000027 0000000000000000 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 00000200 0000000000000030 0000000000000018 I 10 1 8
[ 3] .data PROGBITS 0000000000000000 00000067 0000000000000000 0000000000000000 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 00000067 0000000000000000 0000000000000000 WA 0 0 1
[ 5] .rodata PROGBITS 0000000000000000 00000067 000000000000000a 0000000000000000 A 0 0 1
[ 6] .comment PROGBITS 0000000000000000 00000071 000000000000002e 0000000000000001 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 0000009f 0000000000000000 0000000000000000 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 000000a0 0000000000000038 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 00000230 0000000000000018 0000000000000018 I 10 8 8
[10] .symtab SYMTAB 0000000000000000 000000d8 0000000000000108 0000000000000018 11 9 8
[11] .strtab STRTAB 0000000000000000 000001e0 000000000000001c 0000000000000000 0 0 1
[12] .shstrtab STRTAB 0000000000000000 00000248 0000000000000061 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific)
...
21
LAB) C 프로그램 빌드, 실행, 메모리 레이아웃 이해 (3/3)
 프로그램을 실행하여 프로세스 상태의 메모리 레이아웃 이해
하드웨어 및 운영체제 리뷰
 a.out 프로그램을 실행하고 결과를 보고 프로세스의 메모리 레이아웃에 대해 이해
[root@jvmedu cprogram]# ./a.out
hello
addr(TEXT) => main:0x4005cd, f1:0x4005bd, f2:0x4006ad
addr(CONST) => d:0x400750
addr(DATA) => a:0x601044, a2:0x601048
addr(BSS) => b:0x601050, b2:0x601054
addr(STACK) => c:0x7fff55dabff4, c2:0x7fff55dabff0
addr(HEAP) => name:0xbbf010, score:0xbbf050
22
정적 링킹 (Static Linking) 동적 링킹 (Dynamic Linking)
 최종 실행파일에 필요한 오브젝트 파일들을 미리 링크하여 실행파일에
포함
 실행파일만 있으면 별도의 파일 없이 실행 가능함
 실행파일의 크기가 커지고 라이브러리 갱신 시 모든 파일의 재 컴파일
필요
 정적 링킹은 라이브러리 코드가 실행 파일 내에 저장되기 때문에 배포
와 설치를 간단하게 만듦
 최종 실행파일에 필요한 오브젝트 파일들을 미리 링크하지 않고, 실행
하려고 할 때 필요한 프로그램 모듈을 결합하여 실행을 ���속함
 실행파일의 크기가 작음
 실행파일 이외의 별도의 필요한 모듈을 제공해야 함
 종류
 Build-time Linking
 Run-time Linking
링킹(Linking)의 종류
하드웨어 및 운영체제 리뷰
23
LAB) 링킹 방법 및 링킹 정보 확인 (1/2)
 링킹 방법
 Dynamic Linking
 디폴트 - 아무런 옵션 없이 사용
 Static Linking
 링크 작업시 -static 옵션 사용
하드웨어 및 운영체제 리뷰
cprog.c
#include <stdio.h>
#include <stdlib.h>
int f2(int x);
int a = 10;
int b;
int a2 = 20;
int b2;
int f1(int x) {
return ++x;
}
int main() {
int c = 100, c2;
char *d = "hello";
char *name;
int *score;
name = malloc(50);
score = malloc(20 * sizeof(int));
printf("%sn", d);
printf("addr(TEXT) => main:%p, f1:%p, f2:%pn", main, f1, f2);
printf("addr(CONST) => d:%pn", d);
printf("addr(DATA) => a:%p, a2:%pn", &a, &a2);
printf("addr(BSS) => b:%p, b2:%pn", &b, &b2);
printf("addr(STACK) => c:%p, c2:%pn", &c, &c2);
printf("addr(HEAP) => name:%p, score:%pn", name, score);
return 0;
}
int f2(int x) {
return --x;
}
24
LAB) 링킹 방법 및 링킹 정보 확인 (2/2)
하드웨어 및 운영체제 리뷰
Dynamic Linking Static Linking
 cprog.c 소스파일을 Dynamic Linking으로 a.out_dynamic 실행 파일을 빌드  cprog.c 소스파일을 Static Linking으로 a.out_static 실행 파일 빌드
[root@jvmedu ~]# cd ~/lab/cprogram
[root@jvmedu cprogram]# gcc cprog.c -o a.out_dynamic
[root@jvmedu ~]# cd ~/lab/cprogram
[root@jvmedu cprogram]# gcc -static cprog.c -o a.out_static
 빌드된 a.out_dynamic 실행파일의 파일 정보 확인  빌드된 a.out_static 실행파일의 파일 정보 확인
[root@jvmedu cprogram]# file a.out_dynamic
a.out_dynamic: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.32,
BuildID[sha1]=fef585c519097eb7b47761185909d8d20ec47545, not stripped
[root@jvmedu cprogram]# file a.out_static
a.out_static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux),
statically linked, for GNU/Linux 2.6.32,
BuildID[sha1]=c6acb31c946e031cd81c5c9e54fb55ab2ff73675, not stripped
 빌드된 a.out_dynamic 실행파일의 SYMBOL 정보 확인  빌드된 a.out_static 실행파일의 SYMBOL 정보 확인
[root@jvmedu 01]# nm a.out_dynamic
000000000060103c D a
0000000000601040 D a2
0000000000601048 B b
000000000060104c B b2
0000000000601044 B __bss_start
0000000000601044 b completed.6355
0000000000601038 D __data_start
0000000000601038 W data_start
00000000004004f0 t deregister_tm_clones
0000000000400560 t __do_global_dtors_aux
0000000000600e18 t __do_global_dtors_aux_fini_array_entry
0000000000400738 R __dso_handle
0000000000600e28 d _DYNAMIC
...
[root@jvmedu 01]# nm a.out_static
00000000006bd084 D a
00000000006bd088 D a2
000000000041ce80 T abort
00000000006bf730 B __abort_msg
000000000043de60 W access
000000000043de60 T __access
0000000000490dd0 t add_fdes
000000000044b700 t add_module.isra.1
0000000000440d90 t add_name_to_object.isra.2
00000000006be708 d adds.8362
000000000041d300 T __add_to_environ
0000000000488690 t add_to_global
00000000006bf4c0 V __after_morecore_hook
...
 Dynamic Linking된 바이너리와 Static Linking된 바이너리의 사이즈 비교
[root@jvmedu cprogram]# ls -lh a.out_*
-rwxr-xr-x 1 root root 8.6K Oct 24 14:51 a.out_dynamic
-rwxr-xr-x 1 root root 842K Oct 24 20:05 a.out_static
Static Linking의
사이즈가 97배 더 큼
25
LAB) Shared Library 제작 (1/2)
 Shared Library 제작
 gcc -c -fPIC max.c
 gcc -c -fPIC min.c
 gcc -shared -o libtest.so max.o min.o
하드웨어 및 운영체제 리뷰
 max.c 와 min.c를 빌드하여 object 파일이 생성되었는지 확인
[root@jvmedu ~]# cd ~/lab/cprogram/libTest1/libSrc
[root@jvmedu libSrc]# gcc -c max.c min.c
[root@jvmedu libSrc]# ls -l *.o
-rw-r--r-- 1 root root 1248 Oct 24 15:37 max.o
-rw-r--r-- 1 root root 1248 Oct 24 15:37 min.o
 gcc의 -shared 옵션으로 libtest.o 라는 Shared Library 생성하고 파일 정보를 확인
[root@jvmedu libSrc]# gcc -shared -o libtest.so max.o min.o
[root@jvmedu libSrc]# file libtest.so
libtest.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, BuildID[sha1]=f2167ffbae307a30ecde862fd12777949ce917d4, not stripped
[라이브러리 실습 소스]
26
LAB) Shared Library 제작 (2/2)
 Shared Library 이용
 gcc -c -I<라이브러리헤더파일위치> app.c
 gcc app.o -ltest -L<정적라이브러리위치>
하드웨어 및 운영체제 리뷰
[라이브러리 실습 소스]
 appSrc 폴더로 이동하여, app.c 소스파일을 빌드하여 object 파일을 생성
[root@jvmedu ~]# cd ~/lab/cprogram/libTest1/appSrc
[root@jvmedu appSrc]# gcc -c -I ../include/ app.c
 -L 옵션으로 Library 위치를 명시하고 링크를 수행하고, 실행파일의 파일 정보를 확인
[root@jvmedu appSrc]# gcc app.o -ltest -L ../libSrc/
[root@jvmedu appSrc]# file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked
(uses shared libs), for GNU/Linux 2.6.32,
BuildID[sha1]=91e33185650af97a7869a15687fdcaa324efd8bb, not stripped
 링크된 실행파일을 실행해보고 정상 수행되는지 확인하고, 실패하는 원인은?
[root@jvmedu appSrc]# ./a.out
./a.out: error while loading shared libraries: libtest.so: cannot open shared
object file: No such file or directory
 LD_LIBRARY_PATH 환경변수에 libtest.so 파일경로를 추가하고, a.out 실행
[root@jvmedu appSrc]# export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/root/lab/cprogram/libTest1/libSrc
[root@jvmedu appSrc]# ./a.out
max(5, 2) : 5
min(5, 2) : 2
 a.out 실행파일에 포함된 동적 라이브러를 확인
[root@jvmedu appSrc]# ldd a.out
linux-vdso.so.1 => (0x00007ffd495e4000)
libtest.so => /root/lab/cprogram/libTest1/libSrc/libtest.so (0x00007fa4615ba000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa4611ec000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa4617bc000)
27
LAB) Runtime Loading + Linking 되는 동적 라이브러리 (1/2)
 동적 라이브러리 인터페이스 함수
하드웨어 및 운영체제 리뷰
#include <dlfcn.h>
/* Open the shared object FILE and map it in; return a handle that can be
passed to `dlsym' to get symbol values from it. */
void *dlopen(const char *filename, int flag);
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME. */
void *dlsym(void *handle, const char *symbol);
/* Unmap and close a shared object opened by `dlopen'.
The handle cannot be used again after calling `dlclose'. */
int dlclose(void *handle);
/* When any of the above functions fails, call this function
to return a string describing the error. Each call resets
the error string so that a following call returns null. */
char *dlerror(void);
flag 의미
RTLD_LAZY
 동적 라이브러리가 실행되면서 코드의 정의되지 않은 심볼을 처리
 정의되지 않은 심볼이 있으면 알아볼 수 없는 에러 발생
RTLD_NOW
 dlopen()이 리턴하기 전에 모든 정의되지 않은 심볼을 처리하고,
 그것이 되지 않을 경우 실패. 디버깅시 사용
RTLD_GLOBAL
 라이브러리에 적제되는 외부 심볼들은 그 후에 적재되는 라이브러리에
의해서 가능함
 라이브러리를 여는데 약간의 시간이 더 걸림
28
LAB) Runtime Loading + Linking 되는 동적 라이브러리 (2/2)
 동적 라이브러리 사용 절차
1) 공유 라이브러리 제작 & LD_LIBRARY_PATH에 등록
2) 동적 라이브러리를 사용하는 응용프로그램 작성 : dltest.c
3) 동적 라이브러리를 이용하는 응용프로그램 컴파일
4) 동적 라이브러리를 사용한 응용프로그램 실행
 동적 라이브러리 실습
하드웨어 및 운영체제 리뷰
dltest.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef int (*FP)(int, int);
int main(void) {
void *handle;
FP fp_max, fp_min;
char *error;
handle = dlopen("libtest.so", RTLD_LAZY);
if (!handle) {
fputs(dlerror(), stderr);
exit(1);
}
fp_max = dlsym(handle, "max");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s", error);
exit(1);
}
fp_min = dlsym(handle, "min");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s", error);
exit(1);
}
printf("max(7, 4) : %dn", fp_max(7, 4));
printf("min(5, 2) : %dn", fp_min(5, 2));
dlclose(handle);
return 0;
}
① 공유 라이브러리 제작 & LD_LIBRARY_PATH에 등록
 앞 슬라이드에서 작업 완료
② 동적 라이브러리를 사용하는 응용프로그램 작성 : dltest.c
 옆의 소스 참고
③ 동적 라이브러리를 이용하는 응용프로그램 컴파일
[root@jvmedu ~]# cd ~/lab/cprogram
[root@jvmedu cprogram]# gcc dltest.c -ldl
④ 동적 라이브러리를 사용한 응용프로그램 실행
[root@jvmedu cprogram]# ./a.out
max(7, 4) : 7
min(5, 2) : 2
 a.out 실행파일에 libtest.so 동적 라이브러리 정보가 링크되지 않았음을 확인
[root@jvmedu cprogram]# ldd a.out
linux-vdso.so.1 => (0x00007ffe25de1000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fc92e4f2000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc92e124000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc92e6f6000)
Runtime Loading
Runtime
Linking
29
컴퓨터로 프로그램을 실행한다는것은?
하드웨어 및 운영체제 리뷰
컴파일러 CPU
운영체제
약속
Java Virtual Machine
31
WOCA WORA
Write Once Run Anywhere
Java Virtual Machine
 JAVA의 철학(WORA)을 실현하기 위한 4가지 기술
① Java Programming Language
② Java Class File Format
③ Java Application Programming Interface
④ Java Virtual Machine
32
JAVA 프로그램 수행 과정
Java Virtual Machine
A.java
A.java B.java
B.java C.java
C.java
Java
compiler
A.class
A.class B.class
B.class C.class
C.class
Java source file
Java class file
Object.class
Object.class String.class
String.class
Java API’s class files
Java class file
A.class
A.class B.class
B.class C.class
C.class
Java Virtual
Machine
Compile
Time
Compile
Time
Run
Time
Run
Time
① Java Programming Language
② Class File Format
③ API
④ JVM
33
① Java Programming Language
Java Virtual Machine
object-orientation
multi-threading
structured error-handling
garbage collection
dynamic linking
dynamic extension
Source Code의 재사용
Memory관리에서 해방
Array bound check를 통한 Program의
corruption방지
Object Reference check를 통한 Null
Reference 방지
최신 Software 기술의 적용
최신 Software 기술의 적용
생산성의 극대화
생산성의 극대화
Java Virtual Machine
Other Class
Runtime Memory를
직접 핸들링하지 않음
 Dynamic Linking
 Linking : 개발한 코드에 표준 라이브러리를 연결하는 작업
 Class 파일은 JVM에 로드 된 후 실행이 가능한 형태로 변환되는데, 이
때 표준 라이브러리와 Linking이 수행됨
  Class 파일 사이즈가 적음
 이러한 Link작업이 필요할 때마다 동적으로 이루어짐
34
② Java Class File Format
 Class File Format
 Network Byte Order 사용
 서로 다른 계열의 CPU끼리 데이터 통신시 Byte Order(Big Endian/Little Endian)에 상관없이 전송하기 위한 규약
 Compact한 형태
 ByteCode로 변경
 Platform 독립적
Java Virtual Machine
Presentation
Presentation
클래스파일
 Introduction to Class File Format  Byte Code.pptx
https://www.dropbox.com/s/djz1ogobx38s9v7/Introduction%20to%20Class%20File%20Format%20%26%20Byte%20Code.pptx?dl=0
 Class File Format Image
https://www.dropbox.com/s/dcesinbnh0g7dmj/%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%8C%EC%9D%BC%ED%8F%AC%EB%A7%B7.png?dl=0
35
③ Java API(Application Programming Interface) (1/2)
 Runtime Library의 집합
 Platform Independent
 java -XshowSettings:properties -version
 sun.boot.class.path
Java Virtual Machine
Java API
Java Class
Linux
Linux
jvm.so
jvm.so
Java API
Java Class
jvm.dll
jvm.dll
Windows
Windows
Java API
Java Class
Others
Others
jvm.xxx
Native Library (Dynamic Linking)
Host Operating System
36
③ Java API(Application Programming Interface) (2/2)
 Java 8 Conceptual Diagram
Java Virtual Machine
jadeedu_jvmsw참고문서j2se8-apij2se8.chm
37
④ Java Virtual Machine (1/3)
 JVM Spec
 https://docs.oracle.com/javase/specs/index.html
Java Virtual Machine
Abstract
Specification
A Runtime
Instance
Concrete
Implement
JAVA의 핵심
SINGLE RUNNING
JVM = CONCEPT
VENDOR별 구현
Java Virtual Machine
38
④ Java Virtual Machine (2/3)
 자바를 위한 가상의 머신
Java Virtual Machine
Java API
Java Class
Linux
Linux
jvm.so
Java API
Java Class
jvm.dll
Windows
Windows
Java API
Java Class
Others
Others
jvm.xxx
Java
Virtual
Machine
Host Operating System
39
④ Java Virtual Machine (3/3)
 JVM Architecture
① Class Loader System을 통해 Class 파일들을 JVM으로 로딩한다.
② 로딩된 Class 파일들은 Execution Engine에 의해 해석된다.
③ 이렇게 해석된 프로그램은 Runtime Data Area 배치되어 실질적인 수행이 이루어지게 된다.
④ 이러한 실행 과정 속에서 JVM은 필요에 따라 Thread Synchronization과 Garbage Collection 같은 관리작업을 수행하게 된다
Java Virtual Machine
Java Application
(Real-Time) Operating System
Native
Method
Libraries
Class
Libraries
Class Loader System
Execution
Engine
Run-time
Data Area
Garbage
Collector
Java
Threads
Native
Threads
40
JVM 히스토리
Java Virtual Machine
https://www.geeksforgeeks.org/the-complete-history-of-java-programming-language/
-javaagent
옵션 추가
Modern JAVA
Microsoft Word
문서
41
참고) JVM 구현체 (1/3)
Java Virtual Machine
https://engineering.linecorp.com/ko/blog/line-open-jdk/
42
참고) JVM 구현체 (2/3)
Java Virtual Machine
Vendor Product Commercial Architecture Description
ORACLE Oracle JDK Commercial Hotspot
 Java 8 2019년 1월 이후 License 필요
 검토 시 기준 값으로 사용
AZUL Zing Commercial Zing
 Azul의 자체 아키텍처를 가진 JVM
 상용버전으로, 아키텍처가 독특함
OpenJDK.org OpenJDK OSS Hotspot
 썬 마이크로시스템즈 시절에 만들어진 커뮤니티 그룹으로 OpenJDK가 만들어지는 곳
 커뮤니티에 집중되어 있고 Source는 배포하지만
 Binary 배포는 https://jdk.java.net을 통하여 이루어짐
 https://jdk.java.net에서 배포되는 Binary는 참조용으로 사용할 것을 권장
AZUL Zulu OSS Hotspot
 Azul에서 오픈소스로 제공하는 JDK
 Zing과는 아키텍처 자체가 다르며, OpenJDK를 기반으로 개발되지만 별도의 계약으로 지원을 받을
수 있음
Red Hat/CentOS OpenJDK OSS Hotspot
 레드햇에서 RHEL(Red Hat Enterprise Linux) 또는 CentOS yum repository를 통하여 rpm(binary)으
로 배포
 OS 버전에 따라서 지원되는 버전이 조금씩 다름
AdoptOpenJDK.net OpenJDK OSS
Hotspot
OpenJ9
 OpenJDK 배포를 주 목적으로 하며, 여러 기업의 후원을 받아 개발자들이 운영하는 커뮤니티
 오라클의 지원으로 OpenJDK.org가 주도하는 Hotspot(openjdk)과, IBM의 지원으로 Eclipse가 주도
하는 OpenJ9 VM의 Binary를 모두 제공
 다양한 플랫폼과 VM아키텍처의 Binary를 제공 받을 수 있음
Eclipse.org OpenJ9 OSS OpenJ9
(IBM)
 IBM이 자체 JDK를 Eclipse에 기부하면서 시작된 프로젝트로 VM 아키텍처가 Hotspot과 다름
 IBM 계열의 JDK를 사용 중이던 기업에서 OpenJDK를 고려할 경우 OpenJ9을 고려할 수 있음
 기존의 Hotspot 계열의 JVM과 설정 및 아키텍처에서 다수의 차이가 있음
43
참고) JVM 구현체 (3/3)
 VM Options Explorer
 https://chriswhocodes.com
Java Virtual Machine
44
JVM Option
 JAVA Option
 https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#CBBIJCHG
Java Virtual Machine
Standard Option Non-standard Option
모든 JVM에 공통인 Option
JVM버전에 따라 다름
설정 값, 성능개선 등의 Parameter 등이 포함
- 뒤에 옵션이 들어감 -X option -XX option
Macro한 측면의 제어 Micro한 측면의 제어
Boolean
on : -XX:+option
off : -XX:-option
설정된 Option을 끄거나 새로운 기능을 추가하기 위해 사용
Numeric -XX:option=number
보통 용량 설정
• k, K - Kilobyte
• m, M - Megabyte
• g, G - Gigabyte
• 단위가 없으면 byte로 인식
String -XX:option=string 특정 파일 또는 Path 의 지정에 많이 사용
Non-standard Option
Standard Option
JVM Option -X Option
-XX Option
45
LAB) JVM Standard 옵션 확인
 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
Java Virtual Machine
[root@jvmedu ~]# java -help
Usage: java [-options] class [args...]
(to execute a class)
or java [-options] -jar jarfile [args...]
(to execute a jar file)
where options include:
-d32 use a 32-bit data model if available
-d64 use a 64-bit data model if available
-server to select the server VM
The default VM is server,
because you are running on a server-class machine.
-cp class search path of directories and zip/jar files
-classpath class search path of directories and zip/jar files
A : separated list of directories, JAR archives,
and ZIP archives to search for class files.
-Dname=value
set a system property
-verbose:[class|gc|jni]
enable verbose output
-version print product version and exit
-version:value
Warning: this feature is deprecated and will be removed
in a future release.
require the specified version to run
-showversion print product version and continue
-jre-restrict-search | -no-jre-restrict-search
Warning: this feature is deprecated and will be removed
in a future release.
include/exclude user private JREs in the version search
-? -help print this help message
-X print help on non-standard options
-ea[:packagename...|:classname]
-enableassertions[:packagename...|:classname]
enable assertions with specified granularity
-da[:packagename...|:classname]
-disableassertions[:packagename...|:classname]
disable assertions with specified granularity
-esa | -enablesystemassertions
enable system assertions
-dsa | -disablesystemassertions
disable system assertions
-agentlib:libname[=options]
load native agent library libname, e.g. -agentlib:hprof
see also, -agentlib:jdwp=help and -agentlib:hprof=help
-agentpath:pathname[=options]
load native agent library by full pathname
-javaagent:jarpath[=options]
load Java programming language agent
, see java.lang.instrument
-splash:imagepath
show splash screen with specified image
See http://www.oracle.com/technetwork/java/javase/documentation/index.html
for more details.
46
LAB) JVM Non-Standard -X 옵션 확인
Java Virtual Machine
[root@jvmedu ~]# java -X
-Xmixed mixed mode execution (default)
-Xint interpreted mode execution only
-Xbootclasspath:directories and zip/jar files separated by :
set search path for bootstrap classes and resources
-Xbootclasspath/a:directories and zip/jar files separated by :
append to end of bootstrap class path
-Xbootclasspath/p:directories and zip/jar files separated by :
prepend in front of bootstrap class path
-Xdiag show additional diagnostic messages
-Xnoclassgc disable class garbage collection
-Xincgc enable incremental garbage collection
-Xloggc:file log GC status to a file with time stamps
-Xbatch disable background compilation
-Xmssize set initial Java heap size
-Xmxsize set maximum Java heap size
-Xsssize set java thread stack size
-Xprof output cpu profiling data
-Xfuture enable strictest checks, anticipating future default
-Xrs reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni perform additional checks for JNI functions
-Xshare:off do not attempt to use shared class data
-Xshare:auto use shared class data if possible (default)
-Xshare:on require using shared class data, otherwise fail.
-XshowSettings show all settings and continue
-XshowSettings:all show all settings and continue
-XshowSettings:vm show all vm related settings and continue
-XshowSettings:system (Linux Only) show host system or container configuration and continue
-XshowSettings:properties show all property settings and continue
-XshowSettings:locale show all locale related settings and continue
The -X options are non-standard and subject to change without notice.
47
LAB) JVM 디폴트 설정 값 확인 (1/2)
Java Virtual Machine
 vm 디폴트 설정 값 확인
[root@jvmedu ~]# java -XshowSettings:vm -version
VM settings:
Max. Heap Size (Estimated): 878.50M
Ergonomics Machine Class: server
Using VM: OpenJDK 64-Bit Server VM
 Locale 디폴트 설정 값 확인
[root@jvmedu ~]# java -XshowSettings:locale -version
Locale settings:
default locale = English
default display locale = English (United States)
default format locale = English (United States)
available locales = , ar, ar_AE, ar_BH, ar_DZ, ar_EG, ar_IQ, ar_JO,
ar_KW, ar_LB, ar_LY, ar_MA, ar_OM, ar_QA, ar_SA, ar_SD,
ar_SY, ar_TN, ar_YE, be, be_BY, bg, bg_BG, ca,
ca_ES, cs, cs_CZ, da, da_DK, de, de_AT, de_CH,
de_DE, de_GR, de_LU, el, el_CY, el_GR, en, en_AU,
en_CA, en_GB, en_IE, en_IN, en_MT, en_NZ, en_PH, en_SG,
en_US, en_ZA, es, es_AR, es_BO, es_CL, es_CO, es_CR,
es_CU, es_DO, es_EC, es_ES, es_GT, es_HN, es_MX, es_NI,
es_PA, es_PE, es_PR, es_PY, es_SV, es_US, es_UY, es_VE,
et, et_EE, fi, fi_FI, fr, fr_BE, fr_CA, fr_CH,
fr_FR, fr_LU, ga, ga_IE, hi, hi_IN, hr, hr_HR,
hu, hu_HU, in, in_ID, is, is_IS, it, it_CH,
it_IT, iw, iw_IL, ja, ja_JP, ja_JP_JP_#u-ca-japanese, ko, ko_KR,
lt, lt_LT, lv, lv_LV, mk, mk_MK, ms, ms_MY,
mt, mt_MT, nl, nl_BE, nl_NL, no, no_NO, no_NO_NY,
pl, pl_PL, pt, pt_BR, pt_PT, ro, ro_RO, ru,
ru_RU, sk, sk_SK, sl, sl_SI, sq, sq_AL, sr,
sr_BA, sr_BA_#Latn, sr_CS, sr_ME, sr_ME_#Latn, sr_RS, sr_RS_#Latn, sr__#Latn,
sv, sv_SE, th, th_TH, th_TH_TH_#u-nu-thai, tr, tr_TR, uk,
uk_UA, vi, vi_VN, zh, zh_CN, zh_HK, zh_SG, zh_TW
 Automatic Selection
 Java 5 부터 자동으로 Garbage Collector, Heap Size등을 자동으
로 선택
 Hardware Resource와 OS정보가 기준
 Sever Class와 Client Class의 구분
 java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=64717248
-XX:MaxHeapSize=1035475968
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:+UseParallelGC
openjdk version 1.8.0_302
OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed
mode)
48
LAB) JVM 디폴트 설정 값 확인 (2/2)
Java Virtual Machine
 Property 디폴트 설정 값 확인
[root@jvmedu ~]# java -XshowSettings:properties -version
Property settings:
awt.toolkit = sun.awt.X11.XToolkit
file.encoding = UTF-8
file.encoding.pkg = sun.io
file.separator = /
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
java.awt.printerjob = sun.print.PSPrinterJob
java.class.path = .
java.class.version = 52.0
java.endorsed.dirs = /opt/java/jdk8u302-b08/jre/lib/endorsed
java.ext.dirs = /opt/java/jdk8u302-b08/jre/lib/ext
/usr/java/packages/lib/ext
java.home = /opt/java/jdk8u302-b08/jre
java.io.tmpdir = /tmp
java.library.path =
/root/lab/cprogram/libTest1/libSrc
/usr/java/packages/lib/amd64
/usr/lib64
/lib64
/lib
/usr/lib
java.runtime.name = OpenJDK Runtime Environment
java.runtime.version = 1.8.0_302-b08
java.specification.name = Java Platform API Specification
java.specification.vendor = Oracle Corporation
java.specification.version = 1.8
java.vendor = Temurin
java.vendor.url = https://adoptium.net/
java.vendor.url.bug = https://github.com/adoptium/adoptium-
support/issues
java.version = 1.8.0_302
java.vm.info = mixed mode
java.vm.name = OpenJDK 64-Bit Server VM
java.vm.specification.name = Java Virtual Machine Specification
java.vm.specification.vendor = Oracle Corporation
java.vm.specification.version = 1.8
java.vm.vendor = Temurin
java.vm.version = 25.302-b08
line.separator = n
os.arch = amd64
os.name = Linux
os.version = 3.10.0-1160.el7.x86_64
path.separator = :
sun.arch.data.model = 64
sun.boot.class.path = /opt/java/jdk8u302-b08/jre/lib/resources.jar
/opt/java/jdk8u302-b08/jre/lib/rt.jar
/opt/java/jdk8u302-b08/jre/lib/sunrsasign.jar
/opt/java/jdk8u302-b08/jre/lib/jsse.jar
/opt/java/jdk8u302-b08/jre/lib/jce.jar
/opt/java/jdk8u302-b08/jre/lib/charsets.jar
/opt/java/jdk8u302-b08/jre/lib/jfr.jar
/opt/java/jdk8u302-b08/jre/classes
sun.boot.library.path = /opt/java/jdk8u302-b08/jre/lib/amd64
sun.cpu.endian = little
sun.cpu.isalist =
sun.io.unicode.encoding = UnicodeLittle
sun.java.launcher = SUN_STANDARD
sun.jnu.encoding = UTF-8
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
sun.os.patch.level = unknown
user.country = US
user.dir = /root
user.home = /root
user.language = en
user.name = root
user.timezone =
49
LAB) JVM 디폴트 플래그 값 확인 (2/2)
Java Virtual Machine
 java 디폴트 옵션 값 확인
[root@jvmedu ~]# java -XX:+PrintFlagsFinal -version
[Global flags]
intx ActiveProcessorCount = -1 {product}
uintx AdaptiveSizeDecrementScaleFactor = 4 {product}
uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product}
uintx AdaptiveSizePausePolicy = 0 {product}
....
 힙메모리 관련 디폴트 옵션 값 확인
[root@jvmedu ~]# java -XX:+PrintFlagsFinal -version | grep Heap
bool AggressiveHeap = false {product}
uintx ErgoHeapSizeLimit = 0 {product}
uintx G1HeapRegionSize = 0 {product}
uintx G1HeapWastePercent = 5 {product}
uintx GCHeapFreeLimit = 2 {product}
uintx HeapBaseMinAddress = 2147483648 {pd product}
bool HeapDumpAfterFullGC = false {manageable}
bool HeapDumpBeforeFullGC = false {manageable}
bool HeapDumpOnOutOfMemoryError = false {manageable}
ccstr HeapDumpPath = {manageable}
uintx HeapFirstMaximumCompactionCount = 3 {product}
uintx HeapMaximumCompactionInterval = 20 {product}
uintx HeapSizePerGCThread = 87241520 {product}
uintx InitialHeapSize := 65011712 {product}
uintx InitiatingHeapOccupancyPercent = 45 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapFreeRatio = 100 {manageable}
uintx MaxHeapSize := 1035993088 {product}
uintx MinHeapDeltaBytes := 524288 {product}
uintx MinHeapFreeRatio = 0 {manageable}
bool PrintHeapAtGC = false {product rw}
bool PrintHeapAtGCExtended = false {product rw}
bool PrintHeapAtSIGBREAK = true {product}
Runtime Data Area
(JVM Memory)
51
Runtime Data Area의 구조
Runtime Data Area
Class files
Run-Time Data Area
Method Area
Method Area Heap
Heap JVM Stacks
JVM Stacks
PC Register
PC Register
native method interface
native
method
libraries
Class libraries
“Process로서의 JVM이 프로그램을 수행하기 위해 OS로 부터 할당 받은 메모리 영역“
Native
Method Stacks
Native
Method Stacks
모든 Thread에 공유됨 Thread별로 생성
Class Loader
subsystem
Class Loader
subsystem
Execution
engine
Execution
engine
52
PC(Program Counter) Register (1/2)
 JVM 스펙 문서의 PC Register
 The Java Virtual Machine can support many threads of execution at once. Each Java Virtual Machine
thread has its own pc (program counter) register. At any point, each Java Virtual Machine thread is
executing the code of a single method, namely the current method for that thread. If that method is
not native, the pc register contains the address of the Java Virtual Machine instruction currently
being executed. If the method currently being executed by the thread is native, the value of the Java
Virtual Machine's pc register is undefined. The Java Virtual Machine's pc register is wide enough to
hold a returnAddress or a native pointer on the specific platform.
 (참고) 프로세서(CPU)의 프로그램 실행 절차
Runtime Data Area
FETCH
DECODE
EXECUTE
53
PC(Program Counter) Register (2/2)
 현재 작업하는 내용(Byte Code Instruction)을 CPU에 instruction으로 제공할 때 사용하는 버퍼 공간
 Thread 별로 하나씩 존재하며, Thread가 시작될 때 생성됨
 Thread가 java method를 수행하고 있다면, PC Register에는 현재 수행중인 JVM Instruction을 주소를 가지고 있게 된다.
Runtime Data Area
Thread PC register (Program Counter)
Create
Start
Java Method Call { … }
Native Pointer
Native Pointer
or
Return Address
Current Instruction Address
Current Instruction Address
(native pointer or
method bytecode 시작 offset)
undefined
Native Method Call
54
Java Virtual Machine Stacks (1/2)
 JVM 스펙의 JVM Stacks
 Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual
Machine stack stores frames. A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local
variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never
manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does
not need to be contiguous.
 In the First Edition of The Java® Virtual Machine Specification, the Java Virtual Machine stack was known as the Java stack.
 This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by
the computation. If the Java Virtual Machine stacks are of a fixed size, the size of each Java Virtual Machine stack may be chosen
independently when that stack is created.
 A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of Java Virtual Machine stacks, as well as, in
the case of dynamically expanding or contracting Java Virtual Machine stacks, control over the maximum and minimum sizes.
Runtime Data Area
④
③
②
①
삽입(push) 제거(pop)
①②③④의 순서로 데이터 삽입 ④③②①의 순서로 데이터 제거
스택의 상위(Top)
[그림 5-2] 스택의 구조
 The following exceptional conditions are associated with Java Virtual
Machine stacks:
 If the computation in a thread requires a larger Java Virtual Machine stack than
is permitted, the Java Virtual Machine throws a StackOverflowError.
 If Java Virtual Machine stacks can be dynamically expanded, and expansion is
attempted but insufficient memory can be made available to effect the
expansion, or if insufficient memory can be made available to create the initial
Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an
OutOfMemoryError.
55
Java Virtual Machine Stacks (2/2)
Runtime Data Area
Java
Stack
Java
Stack
Thread
Java
Stack
Java
Stack
Thread
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Thread
Thread
Java
Stack
 Java Stacks
 Java Stack은 Thread의 상태 값을 저장
 Thread당 1개의 Stack Area
 Stack의 모든 데이터는 Thread의 소유
 다른 Thread 접근 불허
 Implement는 JVM Vendor의 재량
 Stack Frame들로 구성됨
 Thread 가 Java Method 를 하나 수행하게 되면 JVM 은 Stack Frame 을 하
나 생성 하여 JVM Stacks 에 Push
 Stack Trace
 ‘kill -3 pid’로 생성되는 Thread Dump는 Stack Frame을 한라인으로 표시한 것
56
LAB) Stack Trace (Thread Dump) 확인 (1/3)
 jpetstore 샘플 웹어플리케이션 실행
Runtime Data Area
 STS를 실행하고 “Tomcat v8.5” 서버 시작
[root@jvmedu ~]# sts
 http://192.168.56.96:8080/jpetstore URL로 접속
Tomcat 시작
http://192.168.56.96:8080/jpetstore/
57
LAB) Stack Trace (Thread Dump) 확인 (2/3)
 VisualVM
 https://visualvm.github.io/
Runtime Data Area
 visualvm 프로그램을 설치하고 Alias 를 등록하고 visualvm 실행 후 visualgc 플러그인 설치
 Tools  Plugins  Available Plugins  Visual GC  Install
[root@jvmedu ~]# cd ~/lab/java-tool
[root@jvmedu java-tool]# unzip visualvm_211.zip
[root@jvmedu java-tool]# echo alias visualvm='/root/lab/java-tool/visualvm_211/bin/visualvm  /dev/null 21 '  ~/.bashrc
[root@jvmedu java-tool]# source ~/.bash_profile
[root@jvmedu java-tool]# visualvm
 Applications 뷰에서 “Tomcat” 오픈  “Threads” 탭  “Thread Dump” 버튼 클릭
58
LAB) Stack Trace (Thread Dump) 확인 (3/3)
 Stack Trace 내용 확인
Runtime Data Area
59
Stack Frame 시뮬레이션
Runtime Data Area
60
Stack Frame (1/7)
 JVM 스펙 상의 Stack Frame
 A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch
exceptions.
 A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that
completion is normal or abrupt (it throws an uncaught exception). Frames are allocated from the Java Virtual Machine stack (§2.5.2) of
the thread creating the frame. Each frame has its own array of local variables (§2.6.1), its own operand stack (§2.6.2), and a reference to
the runtime constant pool (§2.5.5) of the class of the current method.
 A frame may be extended with additional implementation-specific information, such as debugging information.
Runtime Data Area
61
Stack Frame (2/7)
 Stack Frame
 Thread가 수행하고 있는 Application을 Method단위로 기록하는 곳.
 3부분으로 구성됨(Local Variable Section, Operand Stack, Frame Data)
 Method를 호출할 때 Class의 메타정보를 이용하여 적절한 크기(Compile-Time에 이미 결정됨)로 Stack Frame을 생성하여 JVM Stack에 Push 한 후
Method를 실행한다.
 StackTrace는 각 Stack Frame 을 한 라인으로 표현한 것이다.
Runtime Data Area
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Thread
Thread
JvM
Stack
Local Variable
Section
Operand Stack
Frame Data
 Method Parameters
 Local Variables
 JVM의 Work Space
 Constant pool Resolution
 Normal Method Return
 Exception Dispatch
62
Stack Frame (3/7)
 Local Variable Section (1/3)
 Method의 지역변수(Parameter variable, Local variable)를 저장하는 곳
 0-Base 배열로 구성되어 있고, 배열의 index를 통해 data access
 Method parameter는 선언된 순서대로 index가 할당되며, Local variable은 compiler가 알아서 index 할당
Runtime Data Area
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Thread
Thread
JvM
Stack
Local Variable
Section
Operand Stack
Frame Data
 Method Parameters
 Local Variables
 JVM의 Work Space
 Constant pool Resolution
 Normal Method Return
 Exception Dispatch
63
Stack Frame (4/7)
 Local Variable Section (2/3) - JVM 8 스펙문서
 Each frame (§2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is
determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method
associated with the frame (§4.7.3).
 A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables
can hold a value of type long or double.
 Local variables are addressed by indexing. The index of the first local variable is zero. An integer is considered to be an index into the
local variable array if and only if that integer is between zero and one less than the size of the local variable array.
 A value of type long or type double occupies two consecutive local variables. Such a value may only be addressed using the lesser
index. For example, a value of type double stored in the local variable array at index n actually occupies the local variables with indices
n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the
contents of local variable n.
 The Java Virtual Machine does not require n to be even. In intuitive terms, values of types long and double need not be 64-bit aligned
in the local variables array.
 Implementors are free to decide the appropriate way to represent such values using the two local variables reserved for the value.
 The Java Virtual Machine uses local variables to pass parameters on method invocation. On class method invocation, any parameters
are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to
pass a reference to the object on which the instance method is being invoked (this in the Java programming language). Any parameters
are subsequently passed in consecutive local variables starting from local variable 1.
Runtime Data Area
64
// Compiled from LocalVariableSection.java (version 1.8 : 52.0, super bit)
public class LocalVariableSection {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public LocalVariableSection();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 2]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: LocalVariableSection
// Method descriptor #15 (ICJFLjava/lang/Object;DLjava/lang/String;BSZ)I
// Stack: 1, Locals: 13
public int testMethod(int a, char b, long c, float d, java.lang.Object e,
double f, java.lang.String g, byte h, short i, boolean j);
0 iconst_0
1 ireturn
Line numbers:
[pc: 0, line: 4]
Local variable table:
[pc: 0, pc: 2] local: this index: 0 type: LocalVariableSection
[pc: 0, pc: 2] local: a index: 1 type: int
[pc: 0, pc: 2] local: b index: 2 type: char
[pc: 0, pc: 2] local: c index: 3 type: long
[pc: 0, pc: 2] local: d index: 5 type: float
[pc: 0, pc: 2] local: e index: 6 type: java.lang.Object
[pc: 0, pc: 2] local: f index: 7 type: double
[pc: 0, pc: 2] local: g index: 9 type: java.lang.String
[pc: 0, pc: 2] local: h index: 10 type: byte
[pc: 0, pc: 2] local: i index: 11 type: short
[pc: 0, pc: 2] local: j index: 12 type: boolean
}
Stack Frame (5/7)
 Local Variable Section (3/3)
 Local Variable Section의 크기도 Compile-Time에 결정됨
 Primitive Type은 실제 값이 저장되고, Object Type은 객체가 저장되는
Heap의 Reference가 저장
 hidden this
 0번 인덱스에 저장되는 reference형으로, 모든 Local Method, Instance Method
에 자동으로 추가되는 변수로, 여기에 저장된 reference를 통해 Heap에 있는
Class의 Instance 데이터를 찾아가는데 이용
 static으로 선언한 Class Method의 경우에는 “hidden this” 레퍼런스가 존재하지
않음  Method Area에 저장됨
 (샘플) Local Variable Section에서의 Method parameter
Runtime Data Area
class LocalVariableSection {
public int testMethod(int a,
char b,
long c,
float d,
Object e,
double f,
String g,
byte h,
short i,
boolean j) {
return 0;
}
}
index 선언 할당
0 reference hidden this
1 int int a
2 int int b
3
long long c
5 float float d
6 reference Object e
7
double double f
9 reference String g
10 int byte h
11 int short i
12 int boolean j
 int -vs- Integer 어떤 자료형이 효율적일까?
Byte
Code
65
Stack Frame (6/7)
 Operand Stack
 0-Base 배열로 구성
 연산을 위해 사용되는 데이터 및 결과를 Operand Stack에 집어넣고 처리
① 하나의 instruction이 연산을 위해 Operand Stack에 값을 밀어 넣으면(Push)
② 다음 instruction에서는 이 값을 빼서 (Pop) 사용
③ 연산결과가 Operand Stack에 저장되어 지정된 곳으로 보내어 짐
Runtime Data Area
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Thread
Thread
JvM
Stack
Local Variable
Section
Operand Stack
Frame Data
 Method Parameters
 Local Variables
 JVM의 Work Space
 Constant pool Resolution
 Normal Method Return
 Exception Dispatch
66
Stack Frame (7/7)
 Operand Stack 데모
Runtime Data Area
자바 소스 Byte Code
public class OperandStack {
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
}
// Compiled from OperandStack.java (version 1.8 : 52.0, super bit)
public class OperandStack {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public OperandStack();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 2]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: OperandStack
// Method descriptor #6 ()V
// Stack: 2, Locals: 4
public void testMethod();
0 iconst_5
1 istore_1 [a]
2 bipush 6
4 istore_2 [b]
5 iload_1 [a]
6 iload_2 [b]
7 iadd
8 istore_3 [c]
9 return
Line numbers:
[pc: 0, line: 5]
[pc: 2, line: 6]
[pc: 5, line: 7]
[pc: 9, line: 8]
Local variable table:
[pc: 0, pc: 10] local: this index: 0 type: OperandStack
[pc: 2, pc: 10] local: a index: 1 type: int
[pc: 5, pc: 10] local: b index: 2 type: int
[pc: 9, pc: 10] local: c index: 3 type: int
}
67
Stack Frame 메소드 수행 시뮬레이션 (1/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 상수 5를 Operand Stack에 PUSH
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
68
Stack Frame 메소드 수행 시뮬레이션 (2/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 Local Variable Section의 1번 인덱스에 값을 저장
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
69
Stack Frame 메소드 수행 시뮬레이션 (3/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 상수 6을 Openand Stack에 PUSH
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
70
Stack Frame 메소드 수행 시뮬레이션 (4/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 Local Variable Section 2번 인덱스에 6을 저장
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
71
Stack Frame 메소드 수행 시뮬레이션 (5/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 Local Variable Section 1번 인덱스의 값을 LOAD
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
5
72
Stack Frame 메소드 수행 시뮬레이션 (6/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 Local Variable Section 2번 인덱스의 값을 LOAD
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
5
6
73
Stack Frame 메소드 수행 시뮬레이션 (7/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 연산의 대상이 되는 Operand Stack의 값들을 모두 pop하여
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
5
6
 int형 값으로 더한 후 그 결과를 Operand Stack에 PUSH
11
74
Stack Frame 메소드 수행 시뮬레이션 (8/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 Local Variable Section 3번 인덱스에 11을 저장
Operand Stack
PUSH
PUSH
POP
POP
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
11
75
Stack Frame 메소드 수행 시뮬레이션 (9/10)
Runtime Data Area
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7:
iadd
8: istore_3
9: return
store
load
 method의 수행을 마치고 Stack Frame을 삭제
PUSH
PUSH
POP
POP
Operand Stack
명령 설명
iconst_n
iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4
and iconst_5.
These are used to push the constant ints 0 through 5 onto the stack.
istore_n
Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3.
n must be a valid local variable number in the current frame.
bipush
bipush takes a single parameter, and pushes the resulting int value onto the operand
stack.
iload_n
iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that
retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack.
iadd
Pops two integers from the operand stack, adds them, and pushes the integer result
back onto the stack.
return
return is used to return from a method whose return type is void.
All items on the current method's operand stack are discarded. If the current method is
marked as synchronized, then an implicit monitorexit instruction is executed. Then the
current method's frame is discarded, the invoker's frame is reinstated, and control
returns to the invoker.
Local Variables Section
ref hidden this
int a
int b
int c
0
1
2
3
5
6
11
76
Stack Frame 메소드 수행 시뮬레이션 (10/10)
Runtime Data Area
class OperandStack{
public void testMethod() {
int a, b, c;
a = 5;
b = 6;
c = a + b;
}
}
public void operandStack();
Code:
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7: iadd
8: istore_3
9: return
javap –c OperandStack
javap –c OperandStack
Operand
Stack
Local
Variable
Section
int c 3
int b 2
int a 1
hidden this 0
ref ref
5
ref
5
ref
5
6
ref
5
6
ref
5
6
5
ref
5
6
6
5
ref
5
6
13
ref
5
6
13
ref
iconst_5 istore_1 bipush 6 istore_2 iload_1 iload_2 istore_3
iadd return
Local
Variables
Section
Operand
Stack
load
store
PUSH
PUSH
POP
POP
77
Stack Frame - Frame Data (1/3)
 Constant Pool Resolution
 Constant Pool의 Entry를 참조하기 위�� 정보
 Symbolic Reference  Dynamic Reference로 변환하는 과정
 java의 모든 reference는 Symbolic Reference이기 때문에 Resolution이 필요함.
 Normal Method Return
 Method를 호출한 stack frame으로 되돌아 가기 위해 pc register에 이
instruction의 pointer를 보관
 반환 값이 있다면 다음 번 Current Frame(자신을 호출한 메소드의 Stack Frame
의 Operand Stack에 반환 값을 PUSH
 Exception Dispatch
 Exception이 발생하면 이를 핸들링하기 위해 Frame Data를 통해 Exception
Table을 참조
 Frame Data에서 관리하는 Exception정보는 Exception Table에 대한 Reference
 Exception이 발생하면 Exception Table을 참조하여 catch절에 해당하는 Bytecode
로 점프
Runtime Data Area
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Thread
Thread
JvM
Stack
Local Variable
Section
Operand Stack
Frame Data
78
Stack Frame - Frame Data (2/3)
 Constant Pool Resolution
Runtime Data Area
Constant Pool Resolution
Symbolic Reference  Dynamic Reference 변환하는 과정
Symbolic Reference는 Method Area의
Constant Pool에 저장되어 있음
Constant Pool Resolution 결과 = Constant Pool Pointer
 변수나 상수에 접근할 때
 다른 Class를 참조할 때
 Method를 수행할 때
 특정 object가 특정 Class나 Interface에
의존관계가 있는지 확인할 때
Constant Pool Resolution 수행
79
Stack Frame - Frame Data (3/3)
 Exception Dispatch
Runtime Data Area
class JvmInternal2 {
public void operandStack() {
int a, b, c;
a = 5;
b = 6;
try {
c = a + b;
} catch (NullPointerException e){
c = 0;
}
}
}
public void operandStack();
Code:
0: iconst_5
1: istore_1
2: bipush 6
4: istore_2
5: iload_1
6: iload_2
7: iadd
8: istore_3
9: goto 16
12: astore 4
14: iconst_0
15: istore_3
16: return
Exception table:
from to target type
5 9 12 Class java/lang/NullPointerException
javap –c JvmInternal2
javap –c JvmInternal2
from
try 블록이 시작되는
bytecode의 entry number
to
try 블록이 끝나는
bytecode의 entry number
target
exception이 발생했을때 점
프해야할 entry number
type 정의한 exception
예외처리 절차
① try 블럭내에서 예외 발생 또는 throw
② exception 오브젝트의 type의 Class정보와 비교
③ Class정보와 일치하면 target으로 점프
④ Class정보와 일치하지 않으면, JVM은 Current Frame을
종료하고 이 메소드를 호출한 메소드의 Stack Frame에
이 exception을 다시 던져 처리를 반복
80
Native Method Stack
 Java Native Interface
 Java는 JNI를 통해 native function을 호출하고 결과값을 받아 올 수 있다.
 JVM은 native method를 위해 Native Method Stacks 메모리 공간을 마련하였다.
① 어플리케이션에서 native method를 수행
② Native Method Stacks에 새로운 Stack Frame을 생성하여 PUSH하고 native function을 수행
③ native method 수행이 끝나면, native method 를 수행한 java stack frame으로 돌아가는 것이 아니라 새로운 Stack Frame을 생성하여 다시 작업을 수행하게
된다.
Runtime Data Area
Java Stacks
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Stack Frame
Java Method 1
Java Method 2
Native Method 1
Native
Method
Stack
Native Function Call
81
참고) Java Native Interface
 JAVA 8 JNI Spec
 https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html
 자바와 자바 이외의 언어로 만들어진 애플리케이션이나 라이브러리가 상호 작용할 수 있도록 연결시켜 주는 인터페이스
Runtime Data Area
 왜 JNI를 사용하는가?
 JVM에서 지원되지 않은 특정 운영체제 서비스를 이용하고 싶을 때
 자바의 클래스 라이브러리는 방대하고 다양한 서비스를 제공하지만, 특정 플랫폼
에서 제공하는 고유의 서비스의 기능을 모두 포함할 수는 없다. 특히, 특수한 목적
으로 제작된 하드웨어를 자바에서 제어해야 할 필요가 있다고 한다면, 자바만으로
해결하기는 힘들다.
 Native Code(플랫폼에 종속적인 기계어 코드)로 개발된 함수를 이용하고 싶을 때
 부하테스트 수행 시 3rd party가 개발한 보안 모듈 호출
 자바에서 하드웨어 제어를 하고 싶을 때
 기존의 프로그램(C/C++)에서 자바가 제공하는 서비스를 이용하고 싶을 때
 기존에 작성된 프로그램이나 기존의 시스템(legacy)과의 연계 문제
82
LAB) JNI를 이용한 Native Method 호출 (1/5)
 구현 순서
Runtime Data Area
순서 작업 산출물
1 native method 프로토타입이 정의된 자바 소스 작성 HelloNative.java
2 자바 소스 컴파일 HelloNative.class
3 JNI-style header 파일 생성 HelloNative.h
4 native method를 구현한 C 소스파일 작성 HelloNative.c
5 C 소스파일을 compile하여 Native Library 생성 libHelloNative.so
6 HelloNative 자바 프로그램 실행
83
LAB) JNI를 이용한 Native Method 호출 (2/5)
① native method 프로토타입이 정의된 자바 소스 작성
Runtime Data Area
 native method 프로토타입이 정의된 자바 소스 작성
[root@jvmedu ~]# cd ~/lab/jni/ex01
[root@jvmedu ex01]# cat HelloNative.java
public class HelloNative {
private native void nativeMethod(int sleepSec);  함수 원형 정의
static {
System.loadLibrary(HelloNative);
}
 nativeMethod() 가 구현된 라이브러리 로드
private void javaMethod(int sleepSec) {
System.out.println(javaMethod Called....);
this.nativeMethod(sleepSec);
}
 네이티브 메소드 호출
public static void main(String[] args) throws Exception {
int sleepSec = Integer.parseInt(args[0]);
new HelloNative().javaMethod(sleepSec);
}
}
 자바 메소드 호출
② 자바 소스 컴파일
 HelloNative.java 파일을 컴파일하여 HelloNative.class 파일 생성
[root@jvmedu ex01]# javac HelloNative.java
[root@jvmedu ex01]# ls -l HelloNative.class
-rw-r--r-- 1 root root 781 Oct 20 23:21 HelloNative.class
84
LAB) JNI를 이용한 Native Method 호출 (3/5)
③ JNI-style header 파일 생성
Runtime Data Area
 javah 명령으로 이용하여 HelloNative.class에 정의된 native method에 대해 JNI-style의 헤더 파일 생성
[root@jvmedu ex01]# javah HelloNative
 생성된 헤더 파일의 내용 확인
[root@jvmedu ex01]# cat HelloNative.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include jni.h
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern C {
#endif
/*
* Class: HelloNative
* Method: nativeMethod
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_HelloNative_nativeMethod
(JNIEnv *, jobject, jint);
 nativeMethod() 함수 원형
#ifdef __cplusplus
}
#endif
#endif
85
LAB) JNI를 이용한 Native Method 호출 (4/5)
④ native method를 구현한 C 소스파일 작성
Runtime Data Area
 native method를 구현한 C 소스파일 작성
[root@jvmedu ex01]# vi HelloNative.c
HelloNative.c
#include jni.h
#include stdio.h
#include HelloNative.h
JNIEXPORT void JNICALL Java_HelloNative_nativeMethod(JNIEnv *env, jobject obj, jint sleepSec) {
printf(NativeMethod Called.....!n);
sleep(sleepSec);
return;
}
⑤ C 소스파일을 compile하여 Native Library 생성
 gcc 컴파일러를 이용하여 HelloNative.c 를 compile하여 libHelloNative.so 공유 라이브러리 생성
[root@jvmedu ex01]# gcc HelloNative.c -o libHelloNative.so -shared -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -fPIC
[root@jvmedu ex01]# file libHelloNative.so
libHelloNative.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,
BuildID[sha1]=44fd5c90604df6023335a2211b4c39dd3fa797b3, not stripped
86
LAB) JNI를 이용한 Native Method 호출 (5/5)
⑥ HelloNative 자바 프로그램 실행하고 visualvm으로 Thread Dump 생성 후 Native Stack 확인
Runtime Data Area
 -Djava.library.path 옵션을 이용하여 HelloNative 자바 프로그램 실행
[root@jvmedu ex01]# java -Djava.library.path=. HelloNative 1000
javaMethod Called....
NativeMethod Called.....!
 visualvm으로 Thread Dump 를 생성하고 main thread의 Stack Trace를 확인
Top Stack
-Djava.library.path 와 LD_LIBRARY_PATH 환경변수
 native library를 찾을 위치 지정
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
- locked 0x00000000fd47b808 (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
87
Name 설명 비고
Young Generation
object가 생성되면 이 영역에 저장되었다가 시간이 지남에 따라
해제되지 않는 object들은 Old Generation으로 옮겨짐
Minor GC
Eden new 메소드로 object를 생성했을 때 가장 먼저 저장되는 영역
Survivor Alive객체를 저장하기 위한 영역 저장되는 영역
Old Generation Young 영역에서 저장되었던 객체 중에 오래된 객체가 이동되어서 저장되는 영역 Major GC
Permanent Generation
(Metaspace)
Class 메타정보, 메소드 실행 코드, Constant Pool등이 저장되는 영역
JVM Memory Layout
Runtime Data Area
Heap Space Method Area Native Area
Young Generation Old Generation Permanent Generation
(Metaspace - Java 8)
Code Cache
Eden
Survivor
Virtual
Tenured
Virtual
Rntime Constant Pool
Virtual
Thread 1..n
Compile
Native
Virtual
From To
Field  Method Data
PC
Stack
Native
Stack
Code
-Xmn(Young Generation Size)
-Xms(Initial Heap Size)
-Xmx(Maximum Heap Size)
-XX:PermSize=n
88
LAB) Native Out Of Memory (1/3)
 LAB 개요
 C언어로 개발한 Native Method에서 Native Heap에 1mbyte의 메모리를 사용하고 해제(free)하지 않을때 물리메모리를 100% 사용하고 SWAP
메모리도 100%를 다 소진하면 OS에 의해 Java 프로세스가 kill 되는 현상 관찰
Runtime Data Area
NativePmOom.jsp
%@ page language=java contentType=text/html; charset=UTF-8
pageEncoding=UTF-8%
%@ page import=com.jadecross.troubleshoot.oom.nativee.NativeLeak%
물리메모리 부족 데모 - 1회 호출시마다 1m 물리메모리 소진
%
NativeLeak.allocatePhysicalMemory();
%
NativeLeak.java
package com.jadecross.troubleshoot.oom.nativee;
public class NativeLeak {
public static native void allocatePhysicalMemory();
static {
System.loadLibrary(NativeLeak);
}
}
NativeLeak.c
#include jni.h
#include stdio.h
#include stdlib.h
#include memory.h
#include com_jadecross_troubleshoot_oom_nativee_NativeLeak.h
JNIEXPORT void JNICALL
Java_com_jadecross_troubleshoot_oom_nativee_NativeLeak_allocatePhysicalMemory(JNIEnv *env,
jclass classObj)
{
//printf(Allocated 1 mega bytesn);
int i = 0;
for (i; i1000; i++) {
char* bytes = (char*) malloc(1024);
strcpy(bytes,
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000);
}
//printf(t-- Used 1 mega bytesn);
return;
}
89
LAB) Native Out Of Memory (2/3)
Runtime Data Area
① STS 실행후 Tomcat v8.5 서버 실행
[root@jvmedu ~]# sts
② visualvm을 실행하고 visualgc 플러그인 설치
 Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭
[root@jvmedu ~]# visualvm
③ “System Monitor”를 실행하고 Resources 탭을 클릭하여 메모리 상황 관찰
[root@jvmedu ~]# gnome-system-monitor
90
LAB) Native Out Of Memory (3/3)
Runtime Data Area
④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행
⑤ 부하스크립트 파일 오픈 후 “UTG02_NatviePmOom” Thread Group을 Enable한 후 부하를 발생
시키고 메모리 관찰
 스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxJvmTroubleshoot.jmx
 Enable Thread Group : UTG02_NatviePmOom
부하 발생
8080
192.168.56.96
91
Method Area
Class
Data
Class
Data
Class
Data
Class
Data
Class
Data
Class
Data
Class
Data
Class
Data
Method Area
 ClassLoader에 의해 Load된 모든 Type의 메타 정보를 저장하는 메모리 공간
 Class file에서 type에 관한 메타 정보를 추출하여 Method Area에 저장
 Bytecode, 모든 변수, 상수, Reference, Method Data
 Class variable, Class method
 생성자 정보
 JVM이 시작할 때 생성된 GC의 대상
 모든 Thread들에 공유
 Class file에서 type에 관한 메타 정보를 추출하여 Method Area에 저장
 ClassLoader에게 넘겨 받은 Class File 에서 Type 관련 정보를 추출하여 저장
 Method Area의 구현은 Vendor의 재량
 Hotspot JVM
– JDK7 까지는 Permanent Area로 명명하여 Generation Heap의 한 영역으로 포함
– JDK8 이상에서는 MetaSpace로 명명되었고 Native Memory 사용
 IBM에서는 Heap내에 별도의 구분 없이 Class Object 형태로 저장
Runtime Data Area
Thread
Thread Thread
Thread
Thread
Thread
92
LAB) Bytecode 관찰
 Bytecode viewer 설치
 C:jadeedu_jvmswjava_toolbytecode_viewerjclasslib_win64_5_5.exe
 Bytecode viewer 실행 후 Product.class 파일 열기
 Product.class 파일 위치 : C:jadeedu_jvmswlabbytecodeProduct.class
Runtime Data Area
Product.java
package org.mybatis.jpetstore.domain;
import java.io.Serializable;
public class Product implements Serializable {
private static final long serialVersionUID = -7492639752670189553L;
private String productId;
private String categoryId;
private String name;
private String description;
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId.trim(); }
public String getCategoryId() { return categoryId; }
public void setCategoryId(String categoryId) { this.categoryId = categoryId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
@Override
public String toString() { return getName(); }
}
93
Class metadata in Method Area (1/7)
 Type Information
 Type의 전체 이름
 package.class 형태 : Fully Qualified Name
 Type의 직계 Superclass의 전체이름
 Type이 Interface이거나 java.lang.Object Class이거나 SuperClass가 없으면 제외
 Type이 Class인지 Interface인지의 여부
 Type의 modifier (public, abstract, final)
 Interface의 경우 직접 Link되고 있는 객체의 리스트 (참조 순서대로)
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader'
Reference to Class class
94
Class metadata in Method Area (2/7)
 Constant Pool
 Constant Pool은 Type에서 사용된 Constant의 Ordered Set임
 Literal Constant, Type, Field, Method로의 Symbolic Reference가
포함됨
 Constant Pool의 Entry는 Array처럼 index로 접근
 Type에서 사용되는 모든 Type, Method, Field로의 Symbolic
Reference는 Dynamic Linking의 핵심 요소임
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader'
Reference to Class class
95
Class metadata in Method Area (3/7)
 Field Information
 Type에서 선언된 모든 Field의 정보가 순서대로 저장되는 장소
 Field 이름
 Member Variable, Class Variable 을 의미
 Field의 Data Type, 선언된 순서
 Field Modifier
 public, private, protected, static, final, volatile, transient
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader'
Reference to Class class
 참고) Field와 Variable
 Java 에는 4가지 종류의 변수가 있는데, 그것은 각각 Instance Variable, Class Variable, Local Variable, Parameter이다.
 이중 Field라 함은 Instance Variable과 Class Variable을 의미한다.
 이들은 각각 non-static field, static field로 표현되기도 한다.
 그리고 나머지 Local Variable과 Parameter Variable은 각각 Method에 속하는 것으로 Field와 이들을 포함하여 Variable이라고 한다.
96
Class metadata in Method Area (4/7)
 Method Information
 Method 이름
 Method의 Return Type (or void)
 Method Parameter수와 Data Type (순서대로)
 Method Modifier
 public, private, protected, static, final, syncronized, native, abstract
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader'
Reference to Class class
 native 또는 abstract 메소드가 아니라면 다음
의 정보가 추가됨
 Method의 ByteCode
 Method Stack Frame의 Operand Stack 및 Local
variable Section의 크기
 Exception Table
97
Class metadata in Method Area (5/7)
 Class Variables
 Class 변수 = Static 변수
 모든 instance에 공유되며 Instance가 없어도 접근이 가능
 이 변수는 Instance의 것이 아니라 Class에 속함
 Class를 사용하기 이전에 이 변수들은 미리 메모리를 할당 받아 놓아야 함
 final로 선언할 경우에는 이를 변수로 취급하는 것이 아니라 상수로 취급하여
Constant Pool의 Literal Constant로 저장된다.
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader'
Reference to Class class
Class
Instance
Instance
Instance
Instance
Class Variable
98
Class metadata in Method Area (6/7)
 Reference to class ‘ClassLoader’
 하나의 Type이 다른 Type을 참조할 때 JVM은 같은 ClassLoader를 사용
 이런 이유로 Type의 Classloader정보가 필요
 User-Defined Classloader인 경우만 reference를 저장
 Bootstrap Classloader의 경우는 null
 JVM이 Dynamic Linking시 이 정보를 이용하여 참조하는 Class를 같은
Classloader를 통해 Load
 ClassLoader 종류
 Bootstrap ClassLoader
 User-defined ClassLoader
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader’
Reference to Class class
Reference ClassLoader class
99
Class metadata in Method Area (7/7)
 Reference to Class class
 각 Data Type이 load될 때 마다 java.lang.class의 instance가 하나씩 생성
 getClass(), forClass(), isInterface() 등의 Method를 호출할 때 이 Reference를
통해 값을 반환
Runtime Data Area
Class metadata
in
Method Area
Type Information
Constant Pool
Field Information
Method Information
Class Variables
Reference to class ‘ClassLoader’
Reference to Class class
Reference java.lang.Class class
100
LAB) Method Area Out Of Memory (1/6)
 LAB 개요
 Http Request 1번마다 동적으로 Class를 하나 생성하고 JVM에
로드하는 부하를 발생시키고 Permgen(Metaspace) OOM 관찰
Runtime Data Area
PermgenOomDynamicClassLoadFromPermanentClassLoader.java
public class PermgenOomDynamicClassLoadFromPermanentClassLoader extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String dynamicClassName = null;
PermanentClassLoader myClassLoader = null;
Class? dynamicClass = null;
myClassLoader = PermanentClassLoader.getInstance();
try {
dynamicClassName = C_ + UUID.randomUUID().toString().replace(-, );
dynamicClass = myClassLoader.findClass(dynamicClassName);
dynamicClass.getDeclaredMethod(hello).invoke(dynamicClass.newInstance());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
response.getWriter().append(Class : )
.append(dynamicClassName)
.append( Loaded by PermanentClassLoader.... );
}
}
PermanentClassLoader.java
public class PermanentClassLoader extends ClassLoader {
private static PermanentClassLoader _instance = new PermanentClassLoader();
public static PermanentClassLoader getInstance() {
return _instance;
}
@Override
protected Class? findClass(String className) throws ClassNotFoundException {
byte[] classBytes;
try {
classBytes = HelloWorldClassCreator.dump(className);
return defineClass(className, classBytes, 0, classBytes.length);
} catch (Exception e) { }
return super.findClass(className);
}
}
HelloWorldClassCreator.java
public class HelloWorldClassCreator implements Opcodes {
public static byte[] dump(String className) throws Exception {
ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, java/lang/Object, null);
cw.visitSource(className + .java, null);
{
mv = cw.visitMethod(ACC_PUBLIC, init, ()V, null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(1, l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, java/lang/Object, init, ()V, false);
~~~
}
{
mv = cw.visitMethod(ACC_PUBLIC, hello, ()V, null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(6, l0);
mv.visitFieldInsn(GETSTATIC, java/lang/System, out, Ljava/io/PrintStream;);
// mv.visitLdcInsn(bbbbb);
mv.visitLdcInsn(Class :  + className +  Loaded...);
mv.visitMethodInsn(INVOKEVIRTUAL, java/io/PrintStream, println, (Ljava/lang/String;)V, false);
~~~
}
cw.visitEnd();
return cw.toByteArray();
}
}
101
① STS 실행후 Tomcat v7.0 서버 실행
[root@jvmedu ~]# sts
② visualvm을 실행하고 visualgc 플러그인 설치
 Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭
[root@jvmedu ~]# visualvm
③ “System Monitor”를 실행하고 Resources 탭을 클릭하여 메모리 상황 관찰
[root@jvmedu ~]# gnome-system-monitor
LAB) Method Area Out Of Memory (2/6)
Runtime Data Area
Permgen
102
LAB) Method Area Out Of Memory (3/6)
Runtime Data Area
④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행
⑤ 부하스크립트 파일 오픈 후 “UTG04_Permgen(Metaspace) OOM” Thread Group을 Enable한 후 부하를 발생시키고 메모리 관찰
 스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxJvmTroubleshoot.jmx
 Enable Thread Group : UTG04_Permgen(Metaspace) OOM
부하 발생
7080
192.168.56.96
103
LAB) Method Area Out Of Memory (4/6)
Runtime Data Area
104
Java 7 Java 8
LAB) Method Area Out Of Memory (5/6)
 Java8 Metaspace
 Java7의 Permgen 영역은 Native memory 영역으로 이동하여 Metaspace영역으로 명명되었으며, 다만 static object는 Heap영역으로 옮겨
져서 GC의 대상이 최대한 될 수 있도록 하였다.
Runtime Data Area
https://blog.voidmainvoid.net/210
 상기 Java 8의 memory 구조를 보면 알 수 있듯이 Metaspace가
Native Memory를 이용함으로써 java application이 필요한 만큼
계속해서 늘어나는 특징이 있다. 상기 옵션을 통해 알 수 있듯이,
Java 8의 MaxMetaspaceSize는
18,446,744,073,709,547,520Byte(약 16ExaByte, 64bit 프로세서
최고 메모리 상한치)라는 것을 알 수 있다.
 그러므로, Java 8의 -XX:MaxMetaspaceSize를 두지 않는 이상,
Native memory 자원을 최대한 사용한다.
 Metaspace 옵션 설정
 -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m
105
LAB) Method Area Out Of Memory (6/6)
Runtime Data Area
106
Java Heap
 Heap
 Instance나 Array가 저장되는 공간으로 모든 Thread들에 공유
 JVM은 Heap에 메모리를 할당하는 instruction만 존재
 new, newarray, anewarray, multianewarray
 메모리 해제를 위한 명시적인 java code나 byte code도 없으며, 메모리의 해제는 Garbage Collection를 통해 수행됨
 Java Heap의 구현은 Vendor의 재량
 각 JVM Vendor마다 Heap의 구조 및 Garbage Collection, Garbage Collector의 구현이 다름
 참고) new Bytecode
Runtime Data Area
JVM
Java Heap
Object
Instance
Data
Class
Pointer
Array
Thread
Thread Thread
Thread
Thread
Thread
new : create an object
Description
new is used to create object instances.
new takes a single parameter, class, the name of the class of object you want to
create. class is resolved into a Java class (see Chapter 7 for a discussion of how
classes are resolved). Then new determines the size in bytes of instances of the given
class and allocates memory for the new instance from the garbage collected heap. The
fields of the instance are set to the initial value 0 (for numeric and boolean fields),
or null (for reference fields). Next, a reference to the new object is pushed onto the
operand stack.
Note that the new object is initialize uninitialized - before the new object can be used,
one of its init methods must be called using invokespecial, as shown in the example
below.
Exceptions
• OutOfMemoryError - not enough memory to allocate a new instance
• InstantiationError - The class named by type is an abstract class or an interface
Share
107
Heap Space Method Area Native Area
Young Generation Old Generation Permanent Generation
(Metaspace - Java 8)
Code Cache
Eden
Survivor
Virtual
Tenured
Virtual
Rntime Constant Pool
Virtual
Thread 1..n
Compile
Native
Virtual
From To
Field  Method Data
PC
Stack
Native
Stack
Code
-Xmn(Young Generation Size)
-Xms(Initial Heap Size)
-Xmx(Maximum Heap Size)
-XX:PermSize=n
JVM의 Memory - Heap
 Generational Heap
Runtime Data Area
Name 설명 비고
Young Generation
object가 생성되면 이 영역에 저장되었다가 시간이 지남에 따라
해제되지 않는 object들은 Old Generation으로 옮겨짐
Minor GC
Eden new 메소드로 object를 생성했을 때 가장 먼저 저장되는 영역
Survivor Alive객체를 저장하기 위한 영역 저장되는 영역
Old Generation Young 영역에서 저장되었던 객체 중에 오래된 객체가 이동되어서 저장되는 영역 Major GC
Permanent Generation
(Metaspace)
Class 메타정보, 메소드 실행 코드, Constant Pool등이 저장되는 영역
108
LAB) 디폴트 힙 사이즈 확인
 Java5부터 자동으로 Garbage Collector, Heap Size등을 자동으로 선택
 Hardware Resource와 OS정보가 기준
 Sever Class와 Client Class의 구분
 -XX:+PrintCommandLineFlags
 This option prints all command-line flags to the VM
Runtime Data Area
Version 디폴트 Command Line Flags
JAVA 7
[root@jvmedu ~]# /opt/java/jdk7/bin/java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=64717248 -XX:MaxHeapSize=1035475968 -XX:+PrintCommandLineFlags -XX:+UseCompressedOops -
XX:+UseParallelGC
java version 1.7.0_80
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
JAVA 8
[root@jvmedu ~]# /opt/java/jdk8/bin/java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=64717248 -XX:MaxHeapSize=1035475968 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers
-XX:+UseCompressedOops -XX:+UseParallelGC
openjdk version 1.8.0_302
OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed mode)
109
참고) Garbage Collection 방식
Runtime Data Area
110
① STS 실행후 Tomcat v8.5 서버 실행
[root@jvmedu ~]# sts
② visualvm을 실행하고 visualgc 플러그인 설치
 Tools  Plugins  Available Plugins  Visual GC  Install
[root@jvmedu ~]# visualvm
LAB) visualvm을 이용한 JVM 메모리 이해 (1/2)
 visualgc 플러그인
Runtime Data Area
③ Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭
111
④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행
⑤ 부하스크립트 파일 오픈 후 “START”버튼을 클릭하여 부하를 발생시키고 visualvm에서 JVM
메모리 변화를 관찰
 스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxjpetstore.jmx
LAB) visualvm을 이용한 JVM 메모리 이해 (2/2)
 JVM 메모리 관찰
Runtime Data Area
부하 발생
192.168.56.96
112
LAB) java.lang.OutOfMemoryError: Java heap space (1/5)
 LAB) 개요
 Http Request 1번마다 Member 인스턴스를 1개 생성하고 application 객체(Global 객체, 모든 Thread가 공유)의 ArrayList에 추가하여 Heap
Memory 부족해지는 것을 관찰
Runtime Data Area
HeapOom.jsp
%@ page language=java contentType=text/html; charset=UTF-8
pageEncoding=UTF-8%
%@ page import=java.util.*%
%@ page import=com.jadecross.troubleshoot.oom.heap.Member%
Heap 메모리 부족 데모
%
/*
* Http 요청 1건마다 Member객체를 ArrayList에 추가
*/
ArrayListMember members;
members = (ArrayListMember) application.getAttribute(members);
if (members == null) {
members = new ArrayListMember();
application.setAttribute(members, members);
}
members.add(new Member());
%
Member.java
public class Member implements Serializable {
public String name;
public String age;
public String sex;
public String address;
public Member() {
this.name = name_ + UUID.randomUUID().toString();
this.age = age_ + UUID.randomUUID().toString();
this.sex = sex_ + UUID.randomUUID().toString();
this.address = address_ + UUID.randomUUID().toString();
}
}
113
LAB) java.lang.OutOfMemoryError: Java heap space (2/5)
Runtime Data Area
① STS 실행후 Tomcat v7.0 서버 실행
[root@jvmedu ~]# sts
② visualvm을 실행하고 visualgc 플러그인 설치
 Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭
[root@jvmedu ~]# visualvm
③ “System Monitor”를 실행하고 Resources 탭을 클릭하여 메모리 상황 관찰
[root@jvmedu ~]# gnome-system-monitor
Permgen
114
LAB) java.lang.OutOfMemoryError: Java heap space (3/5)
Runtime Data Area
④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행
⑤ 부하스크립트 파일 오픈 후 “UTG05_Heap OOM” Thread Group을 Enable한 후 부하를 발생시키고 Heap 메모리 관찰
 스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxJvmTroubleshoot.jmx
 Enable Thread Group : UTG05_Heap OOM
부하 발생
7080
192.168.56.96
115
LAB) java.lang.OutOfMemoryError: Java heap space (4/5)
Runtime Data Area
116
LAB) java.lang.OutOfMemoryError: Java heap space (5/5)
Runtime Data Area
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf
JVM_트러블슈팅.pdf

More Related Content

JVM_트러블슈팅.pdf

  • 1. IBM Software Group IT Medical Center, JADECROSS © Copyright JADECROSS 2023 jadecross 정환열 이사 2023 JVM 아키텍처 이해를 통한 자바시스템 트러블슈팅 coordinatorj@jadecross.com
  • 2. 목 차 실습 환경설정 하드웨어 및 운영체제 리뷰 Java Virtual Machine Runtime Data Areas(JVM Memory) Process Synchronization(Operating System) Thread Synchronization JAVA 성능분석 도구 Garbage Collection
  • 4. 4  실습파일 다운로드  https://www.dropbox.com/s/znp9247yjl11d7w/jadeedu_jvm_20211103.zip?dl=0  jadeedu_jvm.zip 파일을 C: 하위에 압축 해제 실습 환경설정 (1/8) - 실습파일 다운로드 및 압축 해제 실습 환경설정 jadeedu_jvm_20211103.zip
  • 5. 5 실습 환경설정 (2/8) - VirtualBox 설치  VirtualBox 6 설치  C:jadeedu_jvmswVirtualBox-6.1.16-140961-Win.exe 더블클릭  VirtualBox 환경 설정  파일  환경설정 실습 환경설정 입력 확장 가상 머신 ┗▶ 호스트 키 조합 확장 패키지 추가 Ctrl + Alt C:jadeedu_jvmswOracle_VM_ VirtualBox_Extension_Pack- 6.1.16.vbox-extpack 선택
  • 6. 6 실습 환경설정 (3/8) - VirtualBox 환경설정  네트워크 설정  “Tools  네트워크” 선택  IP 대역 설정  192.168.56.0/24 대역으로 네트워크 설정 실습 환경설정 192.168.56.1/24 192.168.56.1/24 192.168.56.1 192.168.56.100 192.168.56.101 192.168.56.254
  • 7. 7  “NAT 네트워크” 추가  파일  환경 설정  네트워크“   NAT 네트워크 정보  네트워크 이름 : EduNatNetwork  네트워크 CIDR : 192.168.55.0/24 실습 환경설정 (4/8) - VirtualBox 환경설정 실습 환경설정
  • 8. 8 실습 환경설정 (5/8) - 실습 VM 가져오기 및 실행  버튼 클릭하여 VM 가져오기  jvmedu 가상머신 실행 실습 환경설정 계정 : root 암호 : edu “C:jadeedu_jvmvmjvmedujvmedu.vbox” 파일 선택 jvmedu.vbox jvmedu.vbox
  • 9. 9 실습 환경설정 (6/8) - 원격 접속  MobaXterm 실행  jvmedu VM 원격 접속  192.168.56.96 실습 환경설정
  • 10. 10 실습 환경설정 (7/8)  실습 환경 최소 조건  Windows 10, 8G RAM, VirtualBox(하이퍼바이저) 실행 가능해야 함  SSD 디스크 사용할수록 실습이 용이함  최소 VM 자원 설정  vCPU : 4 Core  Memory : 4 GB 실습 환경설정 VirtualBox(Win 10) jvmedu (192.168.56.96) internet 7080 9080
  • 11. 11 실습 환경설정 (8/8)  JAVA_HOME 환경변수 설정 실습 환경설정 C:jadeedu_jvmswjava_tooljdk1.8.0_281  PATH 환경 변수 설정  java.exe가 실행되도록 PATH 환경변수에 %JAVA_HOME%bin 설정
  • 13. 13 요즘 초등학교에서는? 하드웨어 및 운영체제 리뷰 https://www.youtube.com/watch?v=AkFi90lZmXA&feature=youtu.be
  • 14. 14 컴퓨터 시스템 아키텍쳐 하드웨어 및 운영체제 리뷰 Memory CPU Disk Controller USB Controller Graphic Adappter
  • 15. 15 FETCH, DECODE, EXECUTE 하드웨어 및 운영체제 리뷰 https://www.youtube.com/watch?v=Z5JC9Ve1sfI&feature=youtu.be https://www.youtube.com/watch?v=04UGopESS6A&feature=youtu.be (프로그램 내장 방식) https://youtu.be/389itBs7YlE?t=717
  • 16. 16 메모리 계층 구조 하드웨어 및 운영체제 리뷰 https://ko.wikipedia.org/wiki/%EC%A7%90_%EA%B7%B8%EB%A0%88%EC%9D%B4 속도 가격
  • 17. 17 프로그램 = 실행 파일 + 라이브러리  C 실행파일의 빌드 절차 하드웨어 및 운영체제 리뷰 hello.c (소스 파일) hello.i (전처리된 소스파일) hello.o (목적 파일) a.out (실행 파일) hello.s (어셈블리 파일) C 전처리 C 전처리기 cpp C 컴파일 C 컴파일러 cc1 어셈블 어셈블러 as 링킹 링커 ld,collect2 사용자 작성 라이브러리 시스템 내장 라이브러리
  • 18. 18 프로그램 -vs- 프로세스  프로그램  컴파일, 링크 과정을 거쳐 실행할 수 있는 머신코드로 디스크에 저장되어 있음  가상메모리를 사용하는 범용 OS에서는 프로그램의 코드 및 변수의 주소가 이미 결정되어짐  ELF (Executable and Linkable Format)  리눅스의 오브젝트 파일 형식 (원도우즈에서는 PE(Portable Executable) 사용)  https://ko.wikipedia.org/wiki/ELF_파일_형식  프로세스  실행중인 프로그램 하드웨어 및 운영체제 리뷰 Run-Time
  • 19. 19 LAB) C 프로그램 빌드, 실행, 메모리 레이아웃 이해 (1/3)  Static Allocation -vs- Dynamic Allocation 하드웨어 및 운영체제 리뷰 cprog.c #include <stdio.h> #include <stdlib.h> int f2(int x); int a = 10; int a2 = 20; int b; int b2; int f1(int x) { return ++x; } int main() { int c = 100, c2; char *d = "hello"; char *name; int *score; name = malloc(50); score = malloc(20 * sizeof(int)); printf("%sn", d); printf("addr(TEXT) => main:%p, f1:%p, f2:%pn", main, f1, f2); printf("addr(CONST) => d:%pn", d); printf("addr(DATA) => a:%p, a2:%pn", &a, &a2); printf("addr(BSS) => b:%p, b2:%pn", &b, &b2); printf("addr(STACK) => c:%p, c2:%pn", &c, &c2); printf("addr(HEAP) => name:%p, score:%pn", name, score); return 0; } int f2(int x) { return --x; } 프로그램 (HDD) 코드/상수 Static Allocation TEXT 초기화된 전역변수와 정적변수 DATA 초기화되지 않은 전역변수와 정적변수 BSS 프로세스 (RAM) 코드/상수 Static Allocation TEXT 초기화된 전역변수와 정적변수 DATA 초기화되지 않은 전역변수와 정적변수 (0으로 자동 초기화) BSS 동적 할당 메모리 (포인터로 접근) Dynamic Allocation HEAP 지역변수 함수 인자와 리턴 값 STACK 실행
  • 20. 20 LAB) C 프로그램 빌드, 실행, 메모리 레이아웃 이해 (2/3)  C 프로그램 빌드 및 주소 확인 하드웨어 및 운영체제 리뷰  C 언어 소스를 빌드하여 실행파일 생성 [root@jvmedu ~]# cd ~/lab/cprogram [root@jvmedu cprogram]# gcc cprog.c [root@jvmedu cprogram]# ls -l total 16 -rwxr-xr-x 1 root root 8624 Oct 18 14:12 a.out -rw-r--r-- 1 root root 689 Oct 18 14:10 cprog.c  빌드된 실행파일의 형식을 확인 [root@jvmedu cprogram]# file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=d97dd1cd5b319eb15e2d7fe252100ad309f8c1b7, not stripped  a.out 실행파일의 변수 및 함수의 주소를 확인 [root@jvmedu cprogram]# readelf -a a.out  또는 nm a.out 으로 주소 확인 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000027 0000000000000000 AX 0 0 1 [ 2] .rela.text RELA 0000000000000000 00000200 0000000000000030 0000000000000018 I 10 1 8 [ 3] .data PROGBITS 0000000000000000 00000067 0000000000000000 0000000000000000 WA 0 0 1 [ 4] .bss NOBITS 0000000000000000 00000067 0000000000000000 0000000000000000 WA 0 0 1 [ 5] .rodata PROGBITS 0000000000000000 00000067 000000000000000a 0000000000000000 A 0 0 1 [ 6] .comment PROGBITS 0000000000000000 00000071 000000000000002e 0000000000000001 MS 0 0 1 [ 7] .note.GNU-stack PROGBITS 0000000000000000 0000009f 0000000000000000 0000000000000000 0 0 1 [ 8] .eh_frame PROGBITS 0000000000000000 000000a0 0000000000000038 0000000000000000 A 0 0 8 [ 9] .rela.eh_frame RELA 0000000000000000 00000230 0000000000000018 0000000000000018 I 10 8 8 [10] .symtab SYMTAB 0000000000000000 000000d8 0000000000000108 0000000000000018 11 9 8 [11] .strtab STRTAB 0000000000000000 000001e0 000000000000001c 0000000000000000 0 0 1 [12] .shstrtab STRTAB 0000000000000000 00000248 0000000000000061 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) ...
  • 21. 21 LAB) C 프로그램 빌드, 실행, 메모리 레이아웃 이해 (3/3)  프로그램을 실행하여 프로세스 ��태의 메모리 레이아웃 이해 하드웨어 및 운영체제 리뷰  a.out 프로그램을 실행하고 결과를 보고 프로세스의 메모리 레이아웃에 대해 이해 [root@jvmedu cprogram]# ./a.out hello addr(TEXT) => main:0x4005cd, f1:0x4005bd, f2:0x4006ad addr(CONST) => d:0x400750 addr(DATA) => a:0x601044, a2:0x601048 addr(BSS) => b:0x601050, b2:0x601054 addr(STACK) => c:0x7fff55dabff4, c2:0x7fff55dabff0 addr(HEAP) => name:0xbbf010, score:0xbbf050
  • 22. 22 정적 링킹 (Static Linking) 동적 링킹 (Dynamic Linking)  최종 실행파일에 필요한 오브젝트 파일들을 미리 링크하여 실행파일에 포함  실행파일만 있으면 별도의 파일 없이 실행 가능함  실행파일의 크기가 커지고 라이브러리 갱신 시 모든 파일의 재 컴파일 필요  정적 링킹은 라이브러리 코드가 실행 파일 내에 저장되기 때문에 배포 와 설치를 간단하게 만듦  최종 실행파일에 필요한 오브젝트 파일들을 미리 링크하지 않고, 실행 하려고 할 때 필요한 프로그램 모듈을 결합하여 실행을 계속함  실행파일의 크기가 작음  실행파일 이외의 별도의 필요한 모듈을 제공해야 함  종류  Build-time Linking  Run-time Linking 링킹(Linking)의 종류 하드웨어 및 운영체제 리뷰
  • 23. 23 LAB) 링킹 방법 및 링킹 정보 확인 (1/2)  링킹 방법  Dynamic Linking  디폴트 - 아무런 옵션 없이 사용  Static Linking  링크 작업시 -static 옵션 사용 하드웨어 및 운영체제 리뷰 cprog.c #include <stdio.h> #include <stdlib.h> int f2(int x); int a = 10; int b; int a2 = 20; int b2; int f1(int x) { return ++x; } int main() { int c = 100, c2; char *d = "hello"; char *name; int *score; name = malloc(50); score = malloc(20 * sizeof(int)); printf("%sn", d); printf("addr(TEXT) => main:%p, f1:%p, f2:%pn", main, f1, f2); printf("addr(CONST) => d:%pn", d); printf("addr(DATA) => a:%p, a2:%pn", &a, &a2); printf("addr(BSS) => b:%p, b2:%pn", &b, &b2); printf("addr(STACK) => c:%p, c2:%pn", &c, &c2); printf("addr(HEAP) => name:%p, score:%pn", name, score); return 0; } int f2(int x) { return --x; }
  • 24. 24 LAB) 링킹 방법 및 링킹 정보 확인 (2/2) 하드웨어 및 운영체제 리뷰 Dynamic Linking Static Linking  cprog.c 소스파일을 Dynamic Linking으로 a.out_dynamic 실행 파일을 빌드  cprog.c 소스파일을 Static Linking으로 a.out_static 실행 파일 빌드 [root@jvmedu ~]# cd ~/lab/cprogram [root@jvmedu cprogram]# gcc cprog.c -o a.out_dynamic [root@jvmedu ~]# cd ~/lab/cprogram [root@jvmedu cprogram]# gcc -static cprog.c -o a.out_static  빌드된 a.out_dynamic 실행파일의 파일 정보 확인  빌드된 a.out_static 실행파일의 파일 정보 확인 [root@jvmedu cprogram]# file a.out_dynamic a.out_dynamic: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=fef585c519097eb7b47761185909d8d20ec47545, not stripped [root@jvmedu cprogram]# file a.out_static a.out_static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=c6acb31c946e031cd81c5c9e54fb55ab2ff73675, not stripped  빌드된 a.out_dynamic 실행파일의 SYMBOL 정보 확인  빌드된 a.out_static 실행파일의 SYMBOL 정보 확인 [root@jvmedu 01]# nm a.out_dynamic 000000000060103c D a 0000000000601040 D a2 0000000000601048 B b 000000000060104c B b2 0000000000601044 B __bss_start 0000000000601044 b completed.6355 0000000000601038 D __data_start 0000000000601038 W data_start 00000000004004f0 t deregister_tm_clones 0000000000400560 t __do_global_dtors_aux 0000000000600e18 t __do_global_dtors_aux_fini_array_entry 0000000000400738 R __dso_handle 0000000000600e28 d _DYNAMIC ... [root@jvmedu 01]# nm a.out_static 00000000006bd084 D a 00000000006bd088 D a2 000000000041ce80 T abort 00000000006bf730 B __abort_msg 000000000043de60 W access 000000000043de60 T __access 0000000000490dd0 t add_fdes 000000000044b700 t add_module.isra.1 0000000000440d90 t add_name_to_object.isra.2 00000000006be708 d adds.8362 000000000041d300 T __add_to_environ 0000000000488690 t add_to_global 00000000006bf4c0 V __after_morecore_hook ...  Dynamic Linking된 바이너리와 Static Linking된 바이너리의 사이즈 비교 [root@jvmedu cprogram]# ls -lh a.out_* -rwxr-xr-x 1 root root 8.6K Oct 24 14:51 a.out_dynamic -rwxr-xr-x 1 root root 842K Oct 24 20:05 a.out_static Static Linking의 사이즈가 97배 더 큼
  • 25. 25 LAB) Shared Library 제작 (1/2)  Shared Library 제작  gcc -c -fPIC max.c  gcc -c -fPIC min.c  gcc -shared -o libtest.so max.o min.o 하드웨어 및 운영체제 리뷰  max.c 와 min.c를 빌드하여 object 파일이 생성되었는지 확인 [root@jvmedu ~]# cd ~/lab/cprogram/libTest1/libSrc [root@jvmedu libSrc]# gcc -c max.c min.c [root@jvmedu libSrc]# ls -l *.o -rw-r--r-- 1 root root 1248 Oct 24 15:37 max.o -rw-r--r-- 1 root root 1248 Oct 24 15:37 min.o  gcc의 -shared 옵션으로 libtest.o 라는 Shared Library 생성하고 파일 정보를 확인 [root@jvmedu libSrc]# gcc -shared -o libtest.so max.o min.o [root@jvmedu libSrc]# file libtest.so libtest.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f2167ffbae307a30ecde862fd12777949ce917d4, not stripped [라이브러리 실습 소스]
  • 26. 26 LAB) Shared Library 제작 (2/2)  Shared Library 이용  gcc -c -I<라이브러리헤더파일위치> app.c  gcc app.o -ltest -L<정적라이브러리위치> 하드웨어 및 운영체제 리뷰 [라이브러리 실습 소스]  appSrc 폴더로 이동하여, app.c 소스파일을 빌드하여 object 파일을 생성 [root@jvmedu ~]# cd ~/lab/cprogram/libTest1/appSrc [root@jvmedu appSrc]# gcc -c -I ../include/ app.c  -L 옵션으로 Library 위치를 명시하고 링크를 수행하고, 실행파일의 파일 정보를 확인 [root@jvmedu appSrc]# gcc app.o -ltest -L ../libSrc/ [root@jvmedu appSrc]# file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=91e33185650af97a7869a15687fdcaa324efd8bb, not stripped  링크된 실행파일을 실행해보고 정상 수행되는지 확인하고, 실패하는 원인은? [root@jvmedu appSrc]# ./a.out ./a.out: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory  LD_LIBRARY_PATH 환경변수에 libtest.so 파일경로를 추가하고, a.out 실행 [root@jvmedu appSrc]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/root/lab/cprogram/libTest1/libSrc [root@jvmedu appSrc]# ./a.out max(5, 2) : 5 min(5, 2) : 2  a.out 실행파일에 포함된 동적 라이브러를 확인 [root@jvmedu appSrc]# ldd a.out linux-vdso.so.1 => (0x00007ffd495e4000) libtest.so => /root/lab/cprogram/libTest1/libSrc/libtest.so (0x00007fa4615ba000) libc.so.6 => /lib64/libc.so.6 (0x00007fa4611ec000) /lib64/ld-linux-x86-64.so.2 (0x00007fa4617bc000)
  • 27. 27 LAB) Runtime Loading + Linking 되는 동적 라이브러리 (1/2)  동적 라이브러리 인터페이스 함수 하드웨어 및 운영체제 리뷰 #include <dlfcn.h> /* Open the shared object FILE and map it in; return a handle that can be passed to `dlsym' to get symbol values from it. */ void *dlopen(const char *filename, int flag); /* Find the run-time address in the shared object HANDLE refers to of the symbol called NAME. */ void *dlsym(void *handle, const char *symbol); /* Unmap and close a shared object opened by `dlopen'. The handle cannot be used again after calling `dlclose'. */ int dlclose(void *handle); /* When any of the above functions fails, call this function to return a string describing the error. Each call resets the error string so that a following call returns null. */ char *dlerror(void); flag 의미 RTLD_LAZY  동적 라이브러리가 실행되면서 코드의 정의되지 않은 심볼을 처리  정의되지 않은 심볼이 있으면 알아볼 수 없는 에러 발생 RTLD_NOW  dlopen()이 리턴하기 전에 모든 정의되지 않은 심볼을 처리하고,  그것이 되지 않을 경우 실패. 디버깅시 사용 RTLD_GLOBAL  라이브러리에 적제되는 외부 심볼들은 그 후에 적재되는 라이브러리에 의해서 가능함  라이브러리를 여는데 약간의 시간이 더 걸림
  • 28. 28 LAB) Runtime Loading + Linking 되는 동적 라이브러리 (2/2)  동적 라이브러리 사용 절차 1) 공유 라이브러리 제작 & LD_LIBRARY_PATH에 등록 2) 동적 라이브러리를 사용하는 응용프로그램 작성 : dltest.c 3) 동적 라이브러리를 이용하는 응용프로그램 컴파일 4) 동적 라이브러리를 사용한 응용프로그램 실행  동적 라이브러리 실습 하드웨어 및 운영체제 리뷰 dltest.c #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> typedef int (*FP)(int, int); int main(void) { void *handle; FP fp_max, fp_min; char *error; handle = dlopen("libtest.so", RTLD_LAZY); if (!handle) { fputs(dlerror(), stderr); exit(1); } fp_max = dlsym(handle, "max"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s", error); exit(1); } fp_min = dlsym(handle, "min"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s", error); exit(1); } printf("max(7, 4) : %dn", fp_max(7, 4)); printf("min(5, 2) : %dn", fp_min(5, 2)); dlclose(handle); return 0; } ① 공유 라이브러리 제작 & LD_LIBRARY_PATH에 등록  앞 슬라이드에서 작업 완료 ② 동적 라이브러리를 사용하는 응용프로그램 작성 : dltest.c  옆의 소스 참고 ③ 동적 라이브러리를 이용하는 응용프로그램 컴파일 [root@jvmedu ~]# cd ~/lab/cprogram [root@jvmedu cprogram]# gcc dltest.c -ldl ④ 동적 라이브러리를 사용한 응용프로그램 실행 [root@jvmedu cprogram]# ./a.out max(7, 4) : 7 min(5, 2) : 2  a.out 실행파일에 libtest.so 동적 라이브러리 정보가 링크되지 않았음을 확인 [root@jvmedu cprogram]# ldd a.out linux-vdso.so.1 => (0x00007ffe25de1000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fc92e4f2000) libc.so.6 => /lib64/libc.so.6 (0x00007fc92e124000) /lib64/ld-linux-x86-64.so.2 (0x00007fc92e6f6000) Runtime Loading Runtime Linking
  • 29. 29 컴퓨터로 프로그램을 실행한다는것은? 하드웨어 및 운영체제 리뷰 컴파일러 CPU 운영체제 약속
  • 31. 31 WOCA WORA Write Once Run Anywhere Java Virtual Machine  JAVA의 철학(WORA)을 실현하기 위한 4가지 기술 ① Java Programming Language ② Java Class File Format ③ Java Application Programming Interface ④ Java Virtual Machine
  • 32. 32 JAVA 프로그램 수행 과정 Java Virtual Machine A.java A.java B.java B.java C.java C.java Java compiler A.class A.class B.class B.class C.class C.class Java source file Java class file Object.class Object.class String.class String.class Java API’s class files Java class file A.class A.class B.class B.class C.class C.class Java Virtual Machine Compile Time Compile Time Run Time Run Time ① Java Programming Language ② Class File Format ③ API ④ JVM
  • 33. 33 ① Java Programming Language Java Virtual Machine object-orientation multi-threading structured error-handling garbage collection dynamic linking dynamic extension Source Code의 재사용 Memory관리에서 해방 Array bound check를 통한 Program의 corruption방지 Object Reference check를 통한 Null Reference 방지 최신 Software 기술의 적용 최신 Software 기술의 적용 생산성의 극대화 생산성의 극대화 Java Virtual Machine Other Class Runtime Memory를 직접 핸들링하지 않음  Dynamic Linking  Linking : 개발한 코드에 표준 라이브러리를 연결하는 작업  Class 파일은 JVM에 로드 된 후 실행이 가능한 형태로 변환되는데, 이 때 표준 라이브러리와 Linking이 수행됨   Class 파일 사이즈가 적음  이러한 Link작업이 필요할 때마다 동적으로 이루어짐
  • 34. 34 ② Java Class File Format  Class File Format  Network Byte Order 사용  서로 다른 계열의 CPU끼리 데이터 통신시 Byte Order(Big Endian/Little Endian)에 상관없이 전송하기 위한 규약  Compact한 형태  ByteCode로 변경  Platform 독립적 Java Virtual Machine Presentation Presentation 클래스파일  Introduction to Class File Format Byte Code.pptx https://www.dropbox.com/s/djz1ogobx38s9v7/Introduction%20to%20Class%20File%20Format%20%26%20Byte%20Code.pptx?dl=0  Class File Format Image https://www.dropbox.com/s/dcesinbnh0g7dmj/%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%8C%EC%9D%BC%ED%8F%AC%EB%A7%B7.png?dl=0
  • 35. 35 ③ Java API(Application Programming Interface) (1/2)  Runtime Library의 집합  Platform Independent  java -XshowSettings:properties -version  sun.boot.class.path Java Virtual Machine Java API Java Class Linux Linux jvm.so jvm.so Java API Java Class jvm.dll jvm.dll Windows Windows Java API Java Class Others Others jvm.xxx Native Library (Dynamic Linking) Host Operating System
  • 36. 36 ③ Java API(Application Programming Interface) (2/2)  Java 8 Conceptual Diagram Java Virtual Machine jadeedu_jvmsw참고문서j2se8-apij2se8.chm
  • 37. 37 ④ Java Virtual Machine (1/3)  JVM Spec  https://docs.oracle.com/javase/specs/index.html Java Virtual Machine Abstract Specification A Runtime Instance Concrete Implement JAVA의 핵심 SINGLE RUNNING JVM = CONCEPT VENDOR별 구현 Java Virtual Machine
  • 38. 38 ④ Java Virtual Machine (2/3)  자바를 위한 가상의 머신 Java Virtual Machine Java API Java Class Linux Linux jvm.so Java API Java Class jvm.dll Windows Windows Java API Java Class Others Others jvm.xxx Java Virtual Machine Host Operating System
  • 39. 39 ④ Java Virtual Machine (3/3)  JVM Architecture ① Class Loader System을 통해 Class 파일들을 JVM으로 로딩한다. ② 로딩된 Class 파일들은 Execution Engine에 의해 해석된다. ③ 이렇게 해석된 프로그램은 Runtime Data Area 배치되어 실질적인 수행이 이루어지게 된다. ④ 이러한 실행 과정 속에서 JVM은 필요에 따라 Thread Synchronization과 Garbage Collection 같은 관리작업을 수행하게 된다 Java Virtual Machine Java Application (Real-Time) Operating System Native Method Libraries Class Libraries Class Loader System Execution Engine Run-time Data Area Garbage Collector Java Threads Native Threads
  • 40. 40 JVM 히스토리 Java Virtual Machine https://www.geeksforgeeks.org/the-complete-history-of-java-programming-language/ -javaagent 옵션 추가 Modern JAVA Microsoft Word 문서
  • 41. 41 참고) JVM 구현체 (1/3) Java Virtual Machine https://engineering.linecorp.com/ko/blog/line-open-jdk/
  • 42. 42 참고) JVM 구현체 (2/3) Java Virtual Machine Vendor Product Commercial Architecture Description ORACLE Oracle JDK Commercial Hotspot  Java 8 2019년 1월 이후 License 필요  검토 시 기준 값으로 사용 AZUL Zing Commercial Zing  Azul의 자체 아키텍처를 가진 JVM  상용버전으로, 아키텍처가 독특함 OpenJDK.org OpenJDK OSS Hotspot  썬 마이크로시스템즈 시절에 만들어진 커뮤니티 그룹으로 OpenJDK가 만들어지는 곳  커뮤니티에 집중되어 있고 Source는 배포하지만  Binary 배포는 https://jdk.java.net을 통하여 이루어짐  https://jdk.java.net에서 배포되는 Binary는 참조용으로 사용할 것을 권장 AZUL Zulu OSS Hotspot  Azul에서 오픈소스로 제공하는 JDK  Zing과는 아키텍처 자체가 다르며, OpenJDK를 기반으로 개발되지만 별도의 계약으로 지원을 받을 수 있음 Red Hat/CentOS OpenJDK OSS Hotspot  레드햇에서 RHEL(Red Hat Enterprise Linux) 또는 CentOS yum repository를 통하여 rpm(binary)으 로 배포  OS 버전에 따라서 지원되는 버전이 조금씩 다름 AdoptOpenJDK.net OpenJDK OSS Hotspot OpenJ9  OpenJDK 배포를 주 목적으로 하며, 여러 기업의 후원을 받아 개발자들이 운영하는 커뮤니티  오라클의 지원으로 OpenJDK.org가 주도하는 Hotspot(openjdk)과, IBM의 지원으로 Eclipse가 주도 하는 OpenJ9 VM의 Binary를 모두 제공  다양한 플랫폼과 VM아키텍처의 Binary를 제공 받을 수 있음 Eclipse.org OpenJ9 OSS OpenJ9 (IBM)  IBM이 자체 JDK를 Eclipse에 기부하면서 시작된 프로젝트로 VM 아키텍처가 Hotspot과 다름  IBM 계열의 JDK를 사용 중이던 기업에서 OpenJDK를 고려할 경우 OpenJ9을 고려할 수 있음  기존의 Hotspot 계열의 JVM과 설정 및 아키텍처에서 다수의 차이가 있음
  • 43. 43 참고) JVM 구현체 (3/3)  VM Options Explorer  https://chriswhocodes.com Java Virtual Machine
  • 44. 44 JVM Option  JAVA Option  https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#CBBIJCHG Java Virtual Machine Standard Option Non-standard Option 모든 JVM에 공통인 Option JVM버전에 따라 다름 설정 값, 성능개선 등의 Parameter 등이 포함 - 뒤에 옵션이 들어감 -X option -XX option Macro한 측면의 제어 Micro한 측면의 제어 Boolean on : -XX:+option off : -XX:-option 설정된 Option을 끄거나 새로운 기능을 추가하기 위해 사용 Numeric -XX:option=number 보통 용량 설정 • k, K - Kilobyte • m, M - Megabyte • g, G - Gigabyte • 단위가 없으면 byte로 인식 String -XX:option=string 특정 파일 또는 Path 의 지정에 많이 사용 Non-standard Option Standard Option JVM Option -X Option -XX Option
  • 45. 45 LAB) JVM Standard 옵션 확인  https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html Java Virtual Machine [root@jvmedu ~]# java -help Usage: java [-options] class [args...] (to execute a class) or java [-options] -jar jarfile [args...] (to execute a jar file) where options include: -d32 use a 32-bit data model if available -d64 use a 64-bit data model if available -server to select the server VM The default VM is server, because you are running on a server-class machine. -cp class search path of directories and zip/jar files -classpath class search path of directories and zip/jar files A : separated list of directories, JAR archives, and ZIP archives to search for class files. -Dname=value set a system property -verbose:[class|gc|jni] enable verbose output -version print product version and exit -version:value Warning: this feature is deprecated and will be removed in a future release. require the specified version to run -showversion print product version and continue -jre-restrict-search | -no-jre-restrict-search Warning: this feature is deprecated and will be removed in a future release. include/exclude user private JREs in the version search -? -help print this help message -X print help on non-standard options -ea[:packagename...|:classname] -enableassertions[:packagename...|:classname] enable assertions with specified granularity -da[:packagename...|:classname] -disableassertions[:packagename...|:classname] disable assertions with specified granularity -esa | -enablesystemassertions enable system assertions -dsa | -disablesystemassertions disable system assertions -agentlib:libname[=options] load native agent library libname, e.g. -agentlib:hprof see also, -agentlib:jdwp=help and -agentlib:hprof=help -agentpath:pathname[=options] load native agent library by full pathname -javaagent:jarpath[=options] load Java programming language agent , see java.lang.instrument -splash:imagepath show splash screen with specified image See http://www.oracle.com/technetwork/java/javase/documentation/index.html for more details.
  • 46. 46 LAB) JVM Non-Standard -X 옵션 확인 Java Virtual Machine [root@jvmedu ~]# java -X -Xmixed mixed mode execution (default) -Xint interpreted mode execution only -Xbootclasspath:directories and zip/jar files separated by : set search path for bootstrap classes and resources -Xbootclasspath/a:directories and zip/jar files separated by : append to end of bootstrap class path -Xbootclasspath/p:directories and zip/jar files separated by : prepend in front of bootstrap class path -Xdiag show additional diagnostic messages -Xnoclassgc disable class garbage collection -Xincgc enable incremental garbage collection -Xloggc:file log GC status to a file with time stamps -Xbatch disable background compilation -Xmssize set initial Java heap size -Xmxsize set maximum Java heap size -Xsssize set java thread stack size -Xprof output cpu profiling data -Xfuture enable strictest checks, anticipating future default -Xrs reduce use of OS signals by Java/VM (see documentation) -Xcheck:jni perform additional checks for JNI functions -Xshare:off do not attempt to use shared class data -Xshare:auto use shared class data if possible (default) -Xshare:on require using shared class data, otherwise fail. -XshowSettings show all settings and continue -XshowSettings:all show all settings and continue -XshowSettings:vm show all vm related settings and continue -XshowSettings:system (Linux Only) show host system or container configuration and continue -XshowSettings:properties show all property settings and continue -XshowSettings:locale show all locale related settings and continue The -X options are non-standard and subject to change without notice.
  • 47. 47 LAB) JVM 디폴트 설정 값 확인 (1/2) Java Virtual Machine  vm 디폴트 설정 값 확인 [root@jvmedu ~]# java -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 878.50M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM  Locale 디폴트 설정 값 확인 [root@jvmedu ~]# java -XshowSettings:locale -version Locale settings: default locale = English default display locale = English (United States) default format locale = English (United States) available locales = , ar, ar_AE, ar_BH, ar_DZ, ar_EG, ar_IQ, ar_JO, ar_KW, ar_LB, ar_LY, ar_MA, ar_OM, ar_QA, ar_SA, ar_SD, ar_SY, ar_TN, ar_YE, be, be_BY, bg, bg_BG, ca, ca_ES, cs, cs_CZ, da, da_DK, de, de_AT, de_CH, de_DE, de_GR, de_LU, el, el_CY, el_GR, en, en_AU, en_CA, en_GB, en_IE, en_IN, en_MT, en_NZ, en_PH, en_SG, en_US, en_ZA, es, es_AR, es_BO, es_CL, es_CO, es_CR, es_CU, es_DO, es_EC, es_ES, es_GT, es_HN, es_MX, es_NI, es_PA, es_PE, es_PR, es_PY, es_SV, es_US, es_UY, es_VE, et, et_EE, fi, fi_FI, fr, fr_BE, fr_CA, fr_CH, fr_FR, fr_LU, ga, ga_IE, hi, hi_IN, hr, hr_HR, hu, hu_HU, in, in_ID, is, is_IS, it, it_CH, it_IT, iw, iw_IL, ja, ja_JP, ja_JP_JP_#u-ca-japanese, ko, ko_KR, lt, lt_LT, lv, lv_LV, mk, mk_MK, ms, ms_MY, mt, mt_MT, nl, nl_BE, nl_NL, no, no_NO, no_NO_NY, pl, pl_PL, pt, pt_BR, pt_PT, ro, ro_RO, ru, ru_RU, sk, sk_SK, sl, sl_SI, sq, sq_AL, sr, sr_BA, sr_BA_#Latn, sr_CS, sr_ME, sr_ME_#Latn, sr_RS, sr_RS_#Latn, sr__#Latn, sv, sv_SE, th, th_TH, th_TH_TH_#u-nu-thai, tr, tr_TR, uk, uk_UA, vi, vi_VN, zh, zh_CN, zh_HK, zh_SG, zh_TW  Automatic Selection  Java 5 부터 자동으로 Garbage Collector, Heap Size등을 자동으 로 선택  Hardware Resource와 OS정보가 기준  Sever Class와 Client Class의 구분  java -XX:+PrintCommandLineFlags -version -XX:InitialHeapSize=64717248 -XX:MaxHeapSize=1035475968 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC openjdk version 1.8.0_302 OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08) OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed mode)
  • 48. 48 LAB) JVM 디폴트 설정 값 확인 (2/2) Java Virtual Machine  Property 디폴트 설정 값 확인 [root@jvmedu ~]# java -XshowSettings:properties -version Property settings: awt.toolkit = sun.awt.X11.XToolkit file.encoding = UTF-8 file.encoding.pkg = sun.io file.separator = / java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment java.awt.printerjob = sun.print.PSPrinterJob java.class.path = . java.class.version = 52.0 java.endorsed.dirs = /opt/java/jdk8u302-b08/jre/lib/endorsed java.ext.dirs = /opt/java/jdk8u302-b08/jre/lib/ext /usr/java/packages/lib/ext java.home = /opt/java/jdk8u302-b08/jre java.io.tmpdir = /tmp java.library.path = /root/lab/cprogram/libTest1/libSrc /usr/java/packages/lib/amd64 /usr/lib64 /lib64 /lib /usr/lib java.runtime.name = OpenJDK Runtime Environment java.runtime.version = 1.8.0_302-b08 java.specification.name = Java Platform API Specification java.specification.vendor = Oracle Corporation java.specification.version = 1.8 java.vendor = Temurin java.vendor.url = https://adoptium.net/ java.vendor.url.bug = https://github.com/adoptium/adoptium- support/issues java.version = 1.8.0_302 java.vm.info = mixed mode java.vm.name = OpenJDK 64-Bit Server VM java.vm.specification.name = Java Virtual Machine Specification java.vm.specification.vendor = Oracle Corporation java.vm.specification.version = 1.8 java.vm.vendor = Temurin java.vm.version = 25.302-b08 line.separator = n os.arch = amd64 os.name = Linux os.version = 3.10.0-1160.el7.x86_64 path.separator = : sun.arch.data.model = 64 sun.boot.class.path = /opt/java/jdk8u302-b08/jre/lib/resources.jar /opt/java/jdk8u302-b08/jre/lib/rt.jar /opt/java/jdk8u302-b08/jre/lib/sunrsasign.jar /opt/java/jdk8u302-b08/jre/lib/jsse.jar /opt/java/jdk8u302-b08/jre/lib/jce.jar /opt/java/jdk8u302-b08/jre/lib/charsets.jar /opt/java/jdk8u302-b08/jre/lib/jfr.jar /opt/java/jdk8u302-b08/jre/classes sun.boot.library.path = /opt/java/jdk8u302-b08/jre/lib/amd64 sun.cpu.endian = little sun.cpu.isalist = sun.io.unicode.encoding = UnicodeLittle sun.java.launcher = SUN_STANDARD sun.jnu.encoding = UTF-8 sun.management.compiler = HotSpot 64-Bit Tiered Compilers sun.os.patch.level = unknown user.country = US user.dir = /root user.home = /root user.language = en user.name = root user.timezone =
  • 49. 49 LAB) JVM 디폴트 플래그 값 확인 (2/2) Java Virtual Machine  java 디폴트 옵션 값 확인 [root@jvmedu ~]# java -XX:+PrintFlagsFinal -version [Global flags] intx ActiveProcessorCount = -1 {product} uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product} ....  힙메모리 관련 디폴트 옵션 값 확인 [root@jvmedu ~]# java -XX:+PrintFlagsFinal -version | grep Heap bool AggressiveHeap = false {product} uintx ErgoHeapSizeLimit = 0 {product} uintx G1HeapRegionSize = 0 {product} uintx G1HeapWastePercent = 5 {product} uintx GCHeapFreeLimit = 2 {product} uintx HeapBaseMinAddress = 2147483648 {pd product} bool HeapDumpAfterFullGC = false {manageable} bool HeapDumpBeforeFullGC = false {manageable} bool HeapDumpOnOutOfMemoryError = false {manageable} ccstr HeapDumpPath = {manageable} uintx HeapFirstMaximumCompactionCount = 3 {product} uintx HeapMaximumCompactionInterval = 20 {product} uintx HeapSizePerGCThread = 87241520 {product} uintx InitialHeapSize := 65011712 {product} uintx InitiatingHeapOccupancyPercent = 45 {product} uintx LargePageHeapSizeThreshold = 134217728 {product} uintx MaxHeapFreeRatio = 100 {manageable} uintx MaxHeapSize := 1035993088 {product} uintx MinHeapDeltaBytes := 524288 {product} uintx MinHeapFreeRatio = 0 {manageable} bool PrintHeapAtGC = false {product rw} bool PrintHeapAtGCExtended = false {product rw} bool PrintHeapAtSIGBREAK = true {product}
  • 51. 51 Runtime Data Area의 구조 Runtime Data Area Class files Run-Time Data Area Method Area Method Area Heap Heap JVM Stacks JVM Stacks PC Register PC Register native method interface native method libraries Class libraries “Process로서의 JVM이 프로그램을 수행하기 위해 OS로 부터 할당 받은 메모리 영역“ Native Method Stacks Native Method Stacks 모든 Thread에 공유됨 Thread별로 생성 Class Loader subsystem Class Loader subsystem Execution engine Execution engine
  • 52. 52 PC(Program Counter) Register (1/2)  JVM 스펙 문서의 PC Register  The Java Virtual Machine can support many threads of execution at once. Each Java Virtual Machine thread has its own pc (program counter) register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method for that thread. If that method is not native, the pc register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java Virtual Machine's pc register is undefined. The Java Virtual Machine's pc register is wide enough to hold a returnAddress or a native pointer on the specific platform.  (참고) 프로세서(CPU)의 프로그램 실행 절차 Runtime Data Area FETCH DECODE EXECUTE
  • 53. 53 PC(Program Counter) Register (2/2)  현재 작업하는 내용(Byte Code Instruction)을 CPU에 instruction으로 제공할 때 사용하는 버퍼 공간  Thread 별로 하나씩 존재하며, Thread가 시작될 때 생성됨  Thread가 java method를 수행하고 있다면, PC Register에는 현재 수행중인 JVM Instruction을 주소를 가지고 있게 된다. Runtime Data Area Thread PC register (Program Counter) Create Start Java Method Call { … } Native Pointer Native Pointer or Return Address Current Instruction Address Current Instruction Address (native pointer or method bytecode 시작 offset) undefined Native Method Call
  • 54. 54 Java Virtual Machine Stacks (1/2)  JVM 스펙의 JVM Stacks  Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames. A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.  In the First Edition of The Java® Virtual Machine Specification, the Java Virtual Machine stack was known as the Java stack.  This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the Java Virtual Machine stacks are of a fixed size, the size of each Java Virtual Machine stack may be chosen independently when that stack is created.  A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of Java Virtual Machine stacks, as well as, in the case of dynamically expanding or contracting Java Virtual Machine stacks, control over the maximum and minimum sizes. Runtime Data Area ④ ③ ② ① 삽입(push) 제거(pop) ①②③④의 순서로 데이터 삽입 ④③②①의 순서로 데이터 제거 스택의 상위(Top) [그림 5-2] 스택의 구조  The following exceptional conditions are associated with Java Virtual Machine stacks:  If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.  If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.
  • 55. 55 Java Virtual Machine Stacks (2/2) Runtime Data Area Java Stack Java Stack Thread Java Stack Java Stack Thread Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Thread Thread Java Stack  Java Stacks  Java Stack은 Thread의 상태 값을 저장  Thread당 1개의 Stack Area  Stack의 모든 데이터는 Thread의 소유  다른 Thread 접근 불허  Implement는 JVM Vendor의 재량  Stack Frame들로 구성됨  Thread 가 Java Method 를 하나 수행하게 되면 JVM 은 Stack Frame 을 하 나 생성 하여 JVM Stacks 에 Push  Stack Trace  ‘kill -3 pid’로 생성되는 Thread Dump는 Stack Frame을 한라인으로 표시한 것
  • 56. 56 LAB) Stack Trace (Thread Dump) 확인 (1/3)  jpetstore 샘플 웹어플리케이션 실행 Runtime Data Area  STS를 실행하고 “Tomcat v8.5” 서버 시작 [root@jvmedu ~]# sts  http://192.168.56.96:8080/jpetstore URL로 접속 Tomcat 시작 http://192.168.56.96:8080/jpetstore/
  • 57. 57 LAB) Stack Trace (Thread Dump) 확인 (2/3)  VisualVM  https://visualvm.github.io/ Runtime Data Area  visualvm 프로그램을 설치하고 Alias 를 등록하고 visualvm 실행 후 visualgc 플러그인 설치  Tools  Plugins  Available Plugins  Visual GC  Install [root@jvmedu ~]# cd ~/lab/java-tool [root@jvmedu java-tool]# unzip visualvm_211.zip [root@jvmedu java-tool]# echo alias visualvm='/root/lab/java-tool/visualvm_211/bin/visualvm /dev/null 21 ' ~/.bashrc [root@jvmedu java-tool]# source ~/.bash_profile [root@jvmedu java-tool]# visualvm  Applications 뷰에서 “Tomcat” 오픈  “Threads” 탭  “Thread Dump” 버튼 클릭
  • 58. 58 LAB) Stack Trace (Thread Dump) 확인 (3/3)  Stack Trace 내용 확인 Runtime Data Area
  • 60. 60 Stack Frame (1/7)  JVM 스펙 상의 Stack Frame  A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.  A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception). Frames are allocated from the Java Virtual Machine stack (§2.5.2) of the thread creating the frame. Each frame has its own array of local variables (§2.6.1), its own operand stack (§2.6.2), and a reference to the runtime constant pool (§2.5.5) of the class of the current method.  A frame may be extended with additional implementation-specific information, such as debugging information. Runtime Data Area
  • 61. 61 Stack Frame (2/7)  Stack Frame  Thread가 수행하고 있는 Application을 Method단위로 기록하는 곳.  3부분으로 구성됨(Local Variable Section, Operand Stack, Frame Data)  Method를 호출할 때 Class의 메타정보를 이용하여 적절한 크기(Compile-Time에 이미 결정됨)로 Stack Frame을 생성하여 JVM Stack에 Push 한 후 Method를 실행한다.  StackTrace는 각 Stack Frame 을 한 라인으로 표현한 것이다. Runtime Data Area Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Thread Thread JvM Stack Local Variable Section Operand Stack Frame Data  Method Parameters  Local Variables  JVM의 Work Space  Constant pool Resolution  Normal Method Return  Exception Dispatch
  • 62. 62 Stack Frame (3/7)  Local Variable Section (1/3)  Method의 지역변수(Parameter variable, Local variable)를 저장하는 곳  0-Base 배열로 구성되어 있고, 배열의 index를 통해 data access  Method parameter는 선언된 순서대로 index가 할당되며, Local variable은 compiler가 알아서 index 할당 Runtime Data Area Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Thread Thread JvM Stack Local Variable Section Operand Stack Frame Data  Method Parameters  Local Variables  JVM의 Work Space  Constant pool Resolution  Normal Method Return  Exception Dispatch
  • 63. 63 Stack Frame (4/7)  Local Variable Section (2/3) - JVM 8 스펙문서  Each frame (§2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (§4.7.3).  A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables can hold a value of type long or double.  Local variables are addressed by indexing. The index of the first local variable is zero. An integer is considered to be an index into the local variable array if and only if that integer is between zero and one less than the size of the local variable array.  A value of type long or type double occupies two consecutive local variables. Such a value may only be addressed using the lesser index. For example, a value of type double stored in the local variable array at index n actually occupies the local variables with indices n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the contents of local variable n.  The Java Virtual Machine does not require n to be even. In intuitive terms, values of types long and double need not be 64-bit aligned in the local variables array.  Implementors are free to decide the appropriate way to represent such values using the two local variables reserved for the value.  The Java Virtual Machine uses local variables to pass parameters on method invocation. On class method invocation, any parameters are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this in the Java programming language). Any parameters are subsequently passed in consecutive local variables starting from local variable 1. Runtime Data Area
  • 64. 64 // Compiled from LocalVariableSection.java (version 1.8 : 52.0, super bit) public class LocalVariableSection { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public LocalVariableSection(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return Line numbers: [pc: 0, line: 2] Local variable table: [pc: 0, pc: 5] local: this index: 0 type: LocalVariableSection // Method descriptor #15 (ICJFLjava/lang/Object;DLjava/lang/String;BSZ)I // Stack: 1, Locals: 13 public int testMethod(int a, char b, long c, float d, java.lang.Object e, double f, java.lang.String g, byte h, short i, boolean j); 0 iconst_0 1 ireturn Line numbers: [pc: 0, line: 4] Local variable table: [pc: 0, pc: 2] local: this index: 0 type: LocalVariableSection [pc: 0, pc: 2] local: a index: 1 type: int [pc: 0, pc: 2] local: b index: 2 type: char [pc: 0, pc: 2] local: c index: 3 type: long [pc: 0, pc: 2] local: d index: 5 type: float [pc: 0, pc: 2] local: e index: 6 type: java.lang.Object [pc: 0, pc: 2] local: f index: 7 type: double [pc: 0, pc: 2] local: g index: 9 type: java.lang.String [pc: 0, pc: 2] local: h index: 10 type: byte [pc: 0, pc: 2] local: i index: 11 type: short [pc: 0, pc: 2] local: j index: 12 type: boolean } Stack Frame (5/7)  Local Variable Section (3/3)  Local Variable Section의 크기도 Compile-Time에 결정됨  Primitive Type은 실제 값이 저장되고, Object Type은 객체가 저장되는 Heap의 Reference가 저장  hidden this  0번 인덱스에 저장되는 reference형으로, 모든 Local Method, Instance Method 에 자동으로 추가되는 변수로, 여기에 저장된 reference를 통해 Heap에 있는 Class의 Instance 데이터를 찾아가는데 이용  static으로 선언한 Class Method의 경우에는 “hidden this” 레퍼런스가 존재하지 않음  Method Area에 저장됨  (샘플) Local Variable Section에서의 Method parameter Runtime Data Area class LocalVariableSection { public int testMethod(int a, char b, long c, float d, Object e, double f, String g, byte h, short i, boolean j) { return 0; } } index 선언 할당 0 reference hidden this 1 int int a 2 int int b 3 long long c 5 float float d 6 reference Object e 7 double double f 9 reference String g 10 int byte h 11 int short i 12 int boolean j  int -vs- Integer 어떤 자료형이 효율적일까? Byte Code
  • 65. 65 Stack Frame (6/7)  Operand Stack  0-Base 배열로 구성  연산을 위해 사용되는 데이터 및 결과를 Operand Stack에 집어넣고 처리 ① 하나의 instruction이 연산을 위해 Operand Stack에 값을 밀어 넣으면(Push) ② 다음 instruction에서는 이 값을 빼서 (Pop) 사용 ③ 연산결과가 Operand Stack에 저장되어 지정된 곳으로 보내어 짐 Runtime Data Area Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Thread Thread JvM Stack Local Variable Section Operand Stack Frame Data  Method Parameters  Local Variables  JVM의 Work Space  Constant pool Resolution  Normal Method Return  Exception Dispatch
  • 66. 66 Stack Frame (7/7)  Operand Stack 데모 Runtime Data Area 자바 소스 Byte Code public class OperandStack { public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } } // Compiled from OperandStack.java (version 1.8 : 52.0, super bit) public class OperandStack { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public OperandStack(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return Line numbers: [pc: 0, line: 2] Local variable table: [pc: 0, pc: 5] local: this index: 0 type: OperandStack // Method descriptor #6 ()V // Stack: 2, Locals: 4 public void testMethod(); 0 iconst_5 1 istore_1 [a] 2 bipush 6 4 istore_2 [b] 5 iload_1 [a] 6 iload_2 [b] 7 iadd 8 istore_3 [c] 9 return Line numbers: [pc: 0, line: 5] [pc: 2, line: 6] [pc: 5, line: 7] [pc: 9, line: 8] Local variable table: [pc: 0, pc: 10] local: this index: 0 type: OperandStack [pc: 2, pc: 10] local: a index: 1 type: int [pc: 5, pc: 10] local: b index: 2 type: int [pc: 9, pc: 10] local: c index: 3 type: int }
  • 67. 67 Stack Frame 메소드 수행 시뮬레이션 (1/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  상수 5를 Operand Stack에 PUSH Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5
  • 68. 68 Stack Frame 메소드 수행 시뮬레이션 (2/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  Local Variable Section의 1번 인덱스에 값을 저장 Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5
  • 69. 69 Stack Frame 메소드 수행 시뮬레이션 (3/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  상수 6을 Openand Stack에 PUSH Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6
  • 70. 70 Stack Frame 메소드 수행 시뮬레이션 (4/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  Local Variable Section 2번 인덱스에 6을 저장 Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6
  • 71. 71 Stack Frame 메소드 수행 시뮬레이션 (5/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  Local Variable Section 1번 인덱스의 값을 LOAD Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6 5
  • 72. 72 Stack Frame 메소드 수행 시뮬레이션 (6/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  Local Variable Section 2번 인덱스의 값을 LOAD Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6 5 6
  • 73. 73 Stack Frame 메소드 수행 시뮬레이션 (7/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  연산의 대상이 되는 Operand Stack의 값들을 모두 pop하여 Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6 5 6  int형 값으로 더한 후 그 결과를 Operand Stack에 PUSH 11
  • 74. 74 Stack Frame 메소드 수행 시뮬레이션 (8/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  Local Variable Section 3번 인덱스에 11을 저장 Operand Stack PUSH PUSH POP POP 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6 11
  • 75. 75 Stack Frame 메소드 수행 시뮬레이션 (9/10) Runtime Data Area public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return store load  method의 수행을 마치고 Stack Frame을 삭제 PUSH PUSH POP POP Operand Stack 명령 설명 iconst_n iconst_n represents the series of opcodes iconst_0, iconst_1, iconst_2, iconst_3, iconst_4 and iconst_5. These are used to push the constant ints 0 through 5 onto the stack. istore_n Pops an int off the stack and stores it in local variable n, where n is 0, 1, 2 or 3. n must be a valid local variable number in the current frame. bipush bipush takes a single parameter, and pushes the resulting int value onto the operand stack. iload_n iload_n represents the series of opcodes iload_0, iload_1, iload_2, and iload_3 that retrieve a single precision float in local variables 0, 1, 2 or 3 and push it onto the stack. iadd Pops two integers from the operand stack, adds them, and pushes the integer result back onto the stack. return return is used to return from a method whose return type is void. All items on the current method's operand stack are discarded. If the current method is marked as synchronized, then an implicit monitorexit instruction is executed. Then the current method's frame is discarded, the invoker's frame is reinstated, and control returns to the invoker. Local Variables Section ref hidden this int a int b int c 0 1 2 3 5 6 11
  • 76. 76 Stack Frame 메소드 수행 시뮬레이션 (10/10) Runtime Data Area class OperandStack{ public void testMethod() { int a, b, c; a = 5; b = 6; c = a + b; } } public void operandStack(); Code: 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: return javap –c OperandStack javap –c OperandStack Operand Stack Local Variable Section int c 3 int b 2 int a 1 hidden this 0 ref ref 5 ref 5 ref 5 6 ref 5 6 ref 5 6 5 ref 5 6 6 5 ref 5 6 13 ref 5 6 13 ref iconst_5 istore_1 bipush 6 istore_2 iload_1 iload_2 istore_3 iadd return Local Variables Section Operand Stack load store PUSH PUSH POP POP
  • 77. 77 Stack Frame - Frame Data (1/3)  Constant Pool Resolution  Constant Pool의 Entry를 참조하기 위한 정보  Symbolic Reference  Dynamic Reference로 변환하는 과정  java의 모든 reference는 Symbolic Reference이기 때문에 Resolution이 필요함.  Normal Method Return  Method를 호출한 stack frame으로 되돌아 가기 위해 pc register에 이 instruction의 pointer를 보관  반환 값이 있다면 다음 번 Current Frame(자신을 호출한 메소드의 Stack Frame 의 Operand Stack에 반환 값을 PUSH  Exception Dispatch  Exception이 발생하면 이를 핸들링하기 위해 Frame Data를 통해 Exception Table을 참조  Frame Data에서 관리하는 Exception정보는 Exception Table에 대한 Reference  Exception이 발생하면 Exception Table을 참조하여 catch절에 해당하는 Bytecode 로 점프 Runtime Data Area Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Thread Thread JvM Stack Local Variable Section Operand Stack Frame Data
  • 78. 78 Stack Frame - Frame Data (2/3)  Constant Pool Resolution Runtime Data Area Constant Pool Resolution Symbolic Reference  Dynamic Reference 변환하는 과정 Symbolic Reference는 Method Area의 Constant Pool에 저장되어 있음 Constant Pool Resolution 결과 = Constant Pool Pointer  변수나 상수에 접근할 때  다른 Class를 참조할 때  Method를 수행할 때  특정 object가 특정 Class나 Interface에 의존관계가 있는지 확인할 때 Constant Pool Resolution 수행
  • 79. 79 Stack Frame - Frame Data (3/3)  Exception Dispatch Runtime Data Area class JvmInternal2 { public void operandStack() { int a, b, c; a = 5; b = 6; try { c = a + b; } catch (NullPointerException e){ c = 0; } } } public void operandStack(); Code: 0: iconst_5 1: istore_1 2: bipush 6 4: istore_2 5: iload_1 6: iload_2 7: iadd 8: istore_3 9: goto 16 12: astore 4 14: iconst_0 15: istore_3 16: return Exception table: from to target type 5 9 12 Class java/lang/NullPointerException javap –c JvmInternal2 javap –c JvmInternal2 from try 블록이 시작되는 bytecode의 entry number to try 블록이 끝나는 bytecode의 entry number target exception이 발생했을때 점 프해야할 entry number type 정의한 exception 예외처리 절차 ① try 블럭내에서 예외 발생 또는 throw ② exception 오브젝트의 type의 Class정보와 비교 ③ Class정보와 일치하면 target으로 점프 ④ Class정보와 일치하지 않으면, JVM은 Current Frame을 종료하고 이 메소드를 호출한 메소드의 Stack Frame에 이 exception을 다시 던져 처리를 반복
  • 80. 80 Native Method Stack  Java Native Interface  Java는 JNI를 통해 native function을 호출하고 결과값을 받아 올 수 있다.  JVM은 native method를 위해 Native Method Stacks 메모리 공간을 마련하였다. ① 어플리케이션에서 native method를 수행 ② Native Method Stacks에 새로운 Stack Frame을 생성하여 PUSH하고 native function을 수행 ③ native method 수행이 끝나면, native method 를 수행한 java stack frame으로 돌아가는 것이 아니라 새로운 Stack Frame을 생성하여 다시 작업을 수행하게 된다. Runtime Data Area Java Stacks Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Java Method 1 Java Method 2 Native Method 1 Native Method Stack Native Function Call
  • 81. 81 참고) Java Native Interface  JAVA 8 JNI Spec  https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html  자바와 자바 이외의 언어로 만들어진 애플리케이션이나 라이브러리가 상호 작용할 수 있도록 연결시켜 주는 인터페이스 Runtime Data Area  왜 JNI를 사용하는가?  JVM에서 지원되지 않은 특정 운영체제 서비스를 이용하고 싶을 때  자바의 클래스 라이브러리는 방대하고 다양한 서비스를 제공하지만, 특정 플랫폼 에서 제공하는 고유의 서비스의 기능을 모두 포함할 수는 없다. 특히, 특수한 목적 으로 제작된 하드웨어를 자바에서 제어해야 할 필요가 있다고 한다면, 자바만으로 해결하기는 힘들다.  Native Code(플랫폼에 종속적인 기계어 코드)로 개발된 함수를 이용하고 싶을 때  부하테스트 수행 시 3rd party가 개발한 보안 모듈 호출  자바에서 하드웨어 제어를 하고 싶을 때  기존의 프로그램(C/C++)에서 자바가 제공하는 서비스를 이용하고 싶을 때  기존에 작성된 프로그램이나 기존의 시스템(legacy)과의 연계 문제
  • 82. 82 LAB) JNI를 이용한 Native Method 호출 (1/5)  구현 순서 Runtime Data Area 순서 작업 산출물 1 native method 프로토타입이 정의된 자바 소스 작성 HelloNative.java 2 자바 소스 컴파일 HelloNative.class 3 JNI-style header 파일 생성 HelloNative.h 4 native method를 구현한 C 소스파일 작성 HelloNative.c 5 C 소스파일을 compile하여 Native Library 생성 libHelloNative.so 6 HelloNative 자바 프로그램 실행
  • 83. 83 LAB) JNI를 이용한 Native Method 호출 (2/5) ① native method 프로토타입이 정의된 자바 소스 작성 Runtime Data Area  native method 프로토타입이 정의된 자바 소스 작성 [root@jvmedu ~]# cd ~/lab/jni/ex01 [root@jvmedu ex01]# cat HelloNative.java public class HelloNative { private native void nativeMethod(int sleepSec);  함수 원형 정의 static { System.loadLibrary(HelloNative); }  nativeMethod() 가 구현된 라이브러리 로드 private void javaMethod(int sleepSec) { System.out.println(javaMethod Called....); this.nativeMethod(sleepSec); }  네이티브 메소드 호출 public static void main(String[] args) throws Exception { int sleepSec = Integer.parseInt(args[0]); new HelloNative().javaMethod(sleepSec); } }  자바 메소드 호출 ② 자바 소스 컴파일  HelloNative.java 파일을 컴파일하여 HelloNative.class 파일 생성 [root@jvmedu ex01]# javac HelloNative.java [root@jvmedu ex01]# ls -l HelloNative.class -rw-r--r-- 1 root root 781 Oct 20 23:21 HelloNative.class
  • 84. 84 LAB) JNI를 이용한 Native Method 호출 (3/5) ③ JNI-style header 파일 생성 Runtime Data Area  javah 명령으로 이용하여 HelloNative.class에 정의된 native method에 대해 JNI-style의 헤더 파일 생성 [root@jvmedu ex01]# javah HelloNative  생성된 헤더 파일의 내용 확인 [root@jvmedu ex01]# cat HelloNative.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include jni.h /* Header for class HelloNative */ #ifndef _Included_HelloNative #define _Included_HelloNative #ifdef __cplusplus extern C { #endif /* * Class: HelloNative * Method: nativeMethod * Signature: (I)V */ JNIEXPORT void JNICALL Java_HelloNative_nativeMethod (JNIEnv *, jobject, jint);  nativeMethod() 함수 원형 #ifdef __cplusplus } #endif #endif
  • 85. 85 LAB) JNI를 이용한 Native Method 호출 (4/5) ④ native method를 구현한 C 소스파일 작성 Runtime Data Area  native method를 구현한 C 소스파일 작성 [root@jvmedu ex01]# vi HelloNative.c HelloNative.c #include jni.h #include stdio.h #include HelloNative.h JNIEXPORT void JNICALL Java_HelloNative_nativeMethod(JNIEnv *env, jobject obj, jint sleepSec) { printf(NativeMethod Called.....!n); sleep(sleepSec); return; } ⑤ C 소스파일을 compile하여 Native Library 생성  gcc 컴파일러를 이용하여 HelloNative.c 를 compile하여 libHelloNative.so 공유 라이브러리 생성 [root@jvmedu ex01]# gcc HelloNative.c -o libHelloNative.so -shared -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -fPIC [root@jvmedu ex01]# file libHelloNative.so libHelloNative.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=44fd5c90604df6023335a2211b4c39dd3fa797b3, not stripped
  • 86. 86 LAB) JNI를 이용한 Native Method 호출 (5/5) ⑥ HelloNative 자바 프로그램 실행하고 visualvm으로 Thread Dump 생성 후 Native Stack 확인 Runtime Data Area  -Djava.library.path 옵션을 이용하여 HelloNative 자바 프로그램 실행 [root@jvmedu ex01]# java -Djava.library.path=. HelloNative 1000 javaMethod Called.... NativeMethod Called.....!  visualvm으로 Thread Dump 를 생성하고 main thread의 Stack Trace를 확인 Top Stack -Djava.library.path 와 LD_LIBRARY_PATH 환경변수  native library를 찾을 위치 지정 java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:152) at java.net.SocketInputStream.read(SocketInputStream.java:122) at java.io.BufferedInputStream.fill(BufferedInputStream.java:235) at java.io.BufferedInputStream.read(BufferedInputStream.java:254) - locked 0x00000000fd47b808 (a java.io.BufferedInputStream) at java.io.FilterInputStream.read(FilterInputStream.java:83)
  • 87. 87 Name 설명 비고 Young Generation object가 생성되면 이 영역에 저장되었다가 시간이 지남에 따라 해제되지 않는 object들은 Old Generation으로 옮겨짐 Minor GC Eden new 메소드로 object를 생성했을 때 가장 먼저 저장되는 영역 Survivor Alive객체를 저장하기 위한 영역 저장되는 영역 Old Generation Young 영역에서 저장되었던 객체 중에 오래된 객체가 이동되어서 저장되는 영역 Major GC Permanent Generation (Metaspace) Class 메타정보, 메소드 실행 코드, Constant Pool등이 저장되는 영역 JVM Memory Layout Runtime Data Area Heap Space Method Area Native Area Young Generation Old Generation Permanent Generation (Metaspace - Java 8) Code Cache Eden Survivor Virtual Tenured Virtual Rntime Constant Pool Virtual Thread 1..n Compile Native Virtual From To Field Method Data PC Stack Native Stack Code -Xmn(Young Generation Size) -Xms(Initial Heap Size) -Xmx(Maximum Heap Size) -XX:PermSize=n
  • 88. 88 LAB) Native Out Of Memory (1/3)  LAB 개요  C언어로 개발한 Native Method에서 Native Heap에 1mbyte의 메모리를 사용하고 해제(free)하지 않을때 물리메모리를 100% 사용하고 SWAP 메모리도 100%를 다 소진하면 OS에 의해 Java 프로세스가 kill 되는 현상 관찰 Runtime Data Area NativePmOom.jsp %@ page language=java contentType=text/html; charset=UTF-8 pageEncoding=UTF-8% %@ page import=com.jadecross.troubleshoot.oom.nativee.NativeLeak% 물리메모리 부족 데모 - 1회 호출시마다 1m 물리메모리 소진 % NativeLeak.allocatePhysicalMemory(); % NativeLeak.java package com.jadecross.troubleshoot.oom.nativee; public class NativeLeak { public static native void allocatePhysicalMemory(); static { System.loadLibrary(NativeLeak); } } NativeLeak.c #include jni.h #include stdio.h #include stdlib.h #include memory.h #include com_jadecross_troubleshoot_oom_nativee_NativeLeak.h JNIEXPORT void JNICALL Java_com_jadecross_troubleshoot_oom_nativee_NativeLeak_allocatePhysicalMemory(JNIEnv *env, jclass classObj) { //printf(Allocated 1 mega bytesn); int i = 0; for (i; i1000; i++) { char* bytes = (char*) malloc(1024); strcpy(bytes, 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000); } //printf(t-- Used 1 mega bytesn); return; }
  • 89. 89 LAB) Native Out Of Memory (2/3) Runtime Data Area ① STS 실행후 Tomcat v8.5 서버 실행 [root@jvmedu ~]# sts ② visualvm을 실행하고 visualgc 플러그인 설치  Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭 [root@jvmedu ~]# visualvm ③ “System Monitor”를 실행하고 Resources 탭을 클릭하여 메모리 상황 관찰 [root@jvmedu ~]# gnome-system-monitor
  • 90. 90 LAB) Native Out Of Memory (3/3) Runtime Data Area ④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행 ⑤ 부하스크립트 파일 오픈 후 “UTG02_NatviePmOom” Thread Group을 Enable한 후 부하를 발생 시키고 메모리 관찰  스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxJvmTroubleshoot.jmx  Enable Thread Group : UTG02_NatviePmOom 부하 발생 8080 192.168.56.96
  • 91. 91 Method Area Class Data Class Data Class Data Class Data Class Data Class Data Class Data Class Data Method Area  ClassLoader에 의해 Load된 모든 Type의 메타 정보를 저장하는 메모리 공간  Class file에서 type에 관한 메타 정보를 추출하여 Method Area에 저장  Bytecode, 모든 변수, 상수, Reference, Method Data  Class variable, Class method  생성자 정보  JVM이 시작할 때 생성된 GC의 대상  모든 Thread들에 공유  Class file에서 type에 관한 메타 정보를 추출하여 Method Area에 저장  ClassLoader에게 넘겨 받은 Class File 에서 Type 관련 정보를 추출하여 저장  Method Area의 구현은 Vendor의 재량  Hotspot JVM – JDK7 까지는 Permanent Area로 명명하여 Generation Heap의 한 영역으로 포함 – JDK8 이상에서는 MetaSpace로 명명되었고 Native Memory 사용  IBM에서는 Heap내에 별도의 구분 없이 Class Object 형태로 저장 Runtime Data Area Thread Thread Thread Thread Thread Thread
  • 92. 92 LAB) Bytecode 관찰  Bytecode viewer 설치  C:jadeedu_jvmswjava_toolbytecode_viewerjclasslib_win64_5_5.exe  Bytecode viewer 실행 후 Product.class 파일 열기  Product.class 파일 위치 : C:jadeedu_jvmswlabbytecodeProduct.class Runtime Data Area Product.java package org.mybatis.jpetstore.domain; import java.io.Serializable; public class Product implements Serializable { private static final long serialVersionUID = -7492639752670189553L; private String productId; private String categoryId; private String name; private String description; public String getProductId() { return productId; } public void setProductId(String productId) { this.productId = productId.trim(); } public String getCategoryId() { return categoryId; } public void setCategoryId(String categoryId) { this.categoryId = categoryId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return getName(); } }
  • 93. 93 Class metadata in Method Area (1/7)  Type Information  Type의 전체 이름  package.class 형태 : Fully Qualified Name  Type의 직계 Superclass의 전체이름  Type이 Interface이거나 java.lang.Object Class이거나 SuperClass가 없으면 제외  Type이 Class인지 Interface인지의 여부  Type의 modifier (public, abstract, final)  Interface의 경우 직접 Link되고 있는 객체의 리스트 (참조 순서대로) Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader' Reference to Class class
  • 94. 94 Class metadata in Method Area (2/7)  Constant Pool  Constant Pool은 Type에서 사용된 Constant의 Ordered Set임  Literal Constant, Type, Field, Method로의 Symbolic Reference가 포함됨  Constant Pool의 Entry는 Array처럼 index로 접근  Type에서 사용되는 모든 Type, Method, Field로의 Symbolic Reference는 Dynamic Linking의 핵심 요소임 Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader' Reference to Class class
  • 95. 95 Class metadata in Method Area (3/7)  Field Information  Type에서 선언된 모든 Field의 정보가 순서대로 저장되는 장소  Field 이름  Member Variable, Class Variable 을 의미  Field의 Data Type, 선언된 순서  Field Modifier  public, private, protected, static, final, volatile, transient Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader' Reference to Class class  참고) Field와 Variable  Java 에는 4가지 종류의 변수가 있는데, 그것은 각각 Instance Variable, Class Variable, Local Variable, Parameter이다.  이중 Field라 함은 Instance Variable과 Class Variable을 의미한다.  이들은 각각 non-static field, static field로 표현되기도 한다.  그리고 나머지 Local Variable과 Parameter Variable은 각각 Method에 속하는 것으로 Field와 이들을 포함하여 Variable이라고 한다.
  • 96. 96 Class metadata in Method Area (4/7)  Method Information  Method 이름  Method의 Return Type (or void)  Method Parameter수와 Data Type (순서대로)  Method Modifier  public, private, protected, static, final, syncronized, native, abstract Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader' Reference to Class class  native 또는 abstract 메소드가 아니라면 다음 의 정보가 추가됨  Method의 ByteCode  Method Stack Frame의 Operand Stack 및 Local variable Section의 크기  Exception Table
  • 97. 97 Class metadata in Method Area (5/7)  Class Variables  Class 변수 = Static 변수  모든 instance에 공유되며 Instance가 없어도 접근이 가능  이 변수는 Instance의 것이 아니라 Class에 속함  Class를 사용하기 이전에 이 변수들은 미리 메모리를 할당 받아 놓아야 함  final로 선언할 경우에는 이를 변수로 취급하는 것이 아니라 상수로 취급하여 Constant Pool의 Literal Constant로 저장된다. Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader' Reference to Class class Class Instance Instance Instance Instance Class Variable
  • 98. 98 Class metadata in Method Area (6/7)  Reference to class ‘ClassLoader’  하나의 Type이 다른 Type을 참조할 때 JVM은 같은 ClassLoader를 사용  이런 이유로 Type의 Classloader정보가 필요  User-Defined Classloader인 경우만 reference를 저장  Bootstrap Classloader의 경우는 null  JVM이 Dynamic Linking시 이 정보를 이용하여 참조하는 Class를 같은 Classloader를 통해 Load  ClassLoader 종류  Bootstrap ClassLoader  User-defined ClassLoader Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader’ Reference to Class class Reference ClassLoader class
  • 99. 99 Class metadata in Method Area (7/7)  Reference to Class class  각 Data Type이 load될 때 마다 java.lang.class의 instance가 하나씩 생성  getClass(), forClass(), isInterface() 등의 Method를 호출할 때 이 Reference를 통해 값을 반환 Runtime Data Area Class metadata in Method Area Type Information Constant Pool Field Information Method Information Class Variables Reference to class ‘ClassLoader’ Reference to Class class Reference java.lang.Class class
  • 100. 100 LAB) Method Area Out Of Memory (1/6)  LAB 개요  Http Request 1번마다 동적으로 Class를 하나 생성하고 JVM에 로드하는 부하를 발생시키고 Permgen(Metaspace) OOM 관찰 Runtime Data Area PermgenOomDynamicClassLoadFromPermanentClassLoader.java public class PermgenOomDynamicClassLoadFromPermanentClassLoader extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dynamicClassName = null; PermanentClassLoader myClassLoader = null; Class? dynamicClass = null; myClassLoader = PermanentClassLoader.getInstance(); try { dynamicClassName = C_ + UUID.randomUUID().toString().replace(-, ); dynamicClass = myClassLoader.findClass(dynamicClassName); dynamicClass.getDeclaredMethod(hello).invoke(dynamicClass.newInstance()); } catch (Exception ex) { System.out.println(ex.getMessage()); } response.getWriter().append(Class : ) .append(dynamicClassName) .append( Loaded by PermanentClassLoader.... ); } } PermanentClassLoader.java public class PermanentClassLoader extends ClassLoader { private static PermanentClassLoader _instance = new PermanentClassLoader(); public static PermanentClassLoader getInstance() { return _instance; } @Override protected Class? findClass(String className) throws ClassNotFoundException { byte[] classBytes; try { classBytes = HelloWorldClassCreator.dump(className); return defineClass(className, classBytes, 0, classBytes.length); } catch (Exception e) { } return super.findClass(className); } } HelloWorldClassCreator.java public class HelloWorldClassCreator implements Opcodes { public static byte[] dump(String className) throws Exception { ClassWriter cw = new ClassWriter(0); MethodVisitor mv; cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, java/lang/Object, null); cw.visitSource(className + .java, null); { mv = cw.visitMethod(ACC_PUBLIC, init, ()V, null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLineNumber(1, l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, java/lang/Object, init, ()V, false); ~~~ } { mv = cw.visitMethod(ACC_PUBLIC, hello, ()V, null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLineNumber(6, l0); mv.visitFieldInsn(GETSTATIC, java/lang/System, out, Ljava/io/PrintStream;); // mv.visitLdcInsn(bbbbb); mv.visitLdcInsn(Class : + className + Loaded...); mv.visitMethodInsn(INVOKEVIRTUAL, java/io/PrintStream, println, (Ljava/lang/String;)V, false); ~~~ } cw.visitEnd(); return cw.toByteArray(); } }
  • 101. 101 ① STS 실행후 Tomcat v7.0 서버 실행 [root@jvmedu ~]# sts ② visualvm을 실행하고 visualgc 플러그인 설치  Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭 [root@jvmedu ~]# visualvm ③ “System Monitor”를 실행하고 Resources 탭을 클릭하여 메모리 상황 관찰 [root@jvmedu ~]# gnome-system-monitor LAB) Method Area Out Of Memory (2/6) Runtime Data Area Permgen
  • 102. 102 LAB) Method Area Out Of Memory (3/6) Runtime Data Area ④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행 ⑤ 부하스크립트 파일 오픈 후 “UTG04_Permgen(Metaspace) OOM” Thread Group을 Enable한 후 부하를 발생시키고 메모리 관찰  스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxJvmTroubleshoot.jmx  Enable Thread Group : UTG04_Permgen(Metaspace) OOM 부하 발생 7080 192.168.56.96
  • 103. 103 LAB) Method Area Out Of Memory (4/6) Runtime Data Area
  • 104. 104 Java 7 Java 8 LAB) Method Area Out Of Memory (5/6)  Java8 Metaspace  Java7의 Permgen 영역은 Native memory 영역으로 이동하여 Metaspace영역으로 명명되었으며, 다만 static object는 Heap영역으로 옮겨 져서 GC의 대상이 최대한 될 수 있도록 하였다. Runtime Data Area https://blog.voidmainvoid.net/210  상기 Java 8의 memory 구조를 보면 알 수 있듯이 Metaspace가 Native Memory를 이용함으로써 java application이 필요한 만큼 계속해서 늘어나는 특징이 있다. 상기 옵션을 통해 알 수 있듯이, Java 8의 MaxMetaspaceSize는 18,446,744,073,709,547,520Byte(약 16ExaByte, 64bit 프로세서 최고 메모리 상한치)라는 것을 알 수 있다.  그러므로, Java 8의 -XX:MaxMetaspaceSize를 두지 않는 이상, Native memory 자원을 최대한 사용한다.  Metaspace 옵션 설정  -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m
  • 105. 105 LAB) Method Area Out Of Memory (6/6) Runtime Data Area
  • 106. 106 Java Heap  Heap  Instance나 Array가 저장되는 공간으로 모든 Thread들에 공유  JVM은 Heap에 메모리를 할당하는 instruction만 존재  new, newarray, anewarray, multianewarray  메모리 해제를 위한 명시적인 java code나 byte code도 없으며, 메모리의 해제는 Garbage Collection를 통해 수행됨  Java Heap의 구현은 Vendor의 재량  각 JVM Vendor마다 Heap의 구조 및 Garbage Collection, Garbage Collector의 구현이 다름  참고) new Bytecode Runtime Data Area JVM Java Heap Object Instance Data Class Pointer Array Thread Thread Thread Thread Thread Thread new : create an object Description new is used to create object instances. new takes a single parameter, class, the name of the class of object you want to create. class is resolved into a Java class (see Chapter 7 for a discussion of how classes are resolved). Then new determines the size in bytes of instances of the given class and allocates memory for the new instance from the garbage collected heap. The fields of the instance are set to the initial value 0 (for numeric and boolean fields), or null (for reference fields). Next, a reference to the new object is pushed onto the operand stack. Note that the new object is initialize uninitialized - before the new object can be used, one of its init methods must be called using invokespecial, as shown in the example below. Exceptions • OutOfMemoryError - not enough memory to allocate a new instance • InstantiationError - The class named by type is an abstract class or an interface Share
  • 107. 107 Heap Space Method Area Native Area Young Generation Old Generation Permanent Generation (Metaspace - Java 8) Code Cache Eden Survivor Virtual Tenured Virtual Rntime Constant Pool Virtual Thread 1..n Compile Native Virtual From To Field Method Data PC Stack Native Stack Code -Xmn(Young Generation Size) -Xms(Initial Heap Size) -Xmx(Maximum Heap Size) -XX:PermSize=n JVM의 Memory - Heap  Generational Heap Runtime Data Area Name 설명 비고 Young Generation object가 생성되면 이 영역에 저장되었다가 시간이 지남에 따라 해제되지 않는 object들은 Old Generation으로 옮겨짐 Minor GC Eden new 메소드로 object를 생성했을 때 가장 먼저 저장되는 영역 Survivor Alive객체를 저장하기 위한 영역 저장되는 영역 Old Generation Young 영역에서 저장되었던 객체 중에 오래된 객체가 이동되어서 저장되는 영역 Major GC Permanent Generation (Metaspace) Class 메타정보, 메소드 실행 코드, Constant Pool등이 저장되는 영역
  • 108. 108 LAB) 디폴트 힙 사이즈 확인  Java5부터 자동으로 Garbage Collector, Heap Size등을 자동으로 선택  Hardware Resource와 OS정보가 기준  Sever Class와 Client Class의 구분  -XX:+PrintCommandLineFlags  This option prints all command-line flags to the VM Runtime Data Area Version 디폴트 Command Line Flags JAVA 7 [root@jvmedu ~]# /opt/java/jdk7/bin/java -XX:+PrintCommandLineFlags -version -XX:InitialHeapSize=64717248 -XX:MaxHeapSize=1035475968 -XX:+PrintCommandLineFlags -XX:+UseCompressedOops - XX:+UseParallelGC java version 1.7.0_80 Java(TM) SE Runtime Environment (build 1.7.0_80-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode) JAVA 8 [root@jvmedu ~]# /opt/java/jdk8/bin/java -XX:+PrintCommandLineFlags -version -XX:InitialHeapSize=64717248 -XX:MaxHeapSize=1035475968 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC openjdk version 1.8.0_302 OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08) OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed mode)
  • 109. 109 참고) Garbage Collection 방식 Runtime Data Area
  • 110. 110 ① STS 실행후 Tomcat v8.5 서버 실행 [root@jvmedu ~]# sts ② visualvm을 실행하고 visualgc 플러그인 설치  Tools  Plugins  Available Plugins  Visual GC  Install [root@jvmedu ~]# visualvm LAB) visualvm을 이용한 JVM 메모리 이해 (1/2)  visualgc 플러그인 Runtime Data Area ③ Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭
  • 111. 111 ④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행 ⑤ 부하스크립트 파일 오픈 후 “START”버튼을 클릭하여 부하를 발생시키고 visualvm에서 JVM 메모리 변화를 관찰  스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxjpetstore.jmx LAB) visualvm을 이용한 JVM 메모리 이해 (2/2)  JVM 메모리 관찰 Runtime Data Area 부하 발생 192.168.56.96
  • 112. 112 LAB) java.lang.OutOfMemoryError: Java heap space (1/5)  LAB) 개요  Http Request 1번마다 Member 인스턴스를 1개 생성하고 application 객체(Global 객체, 모든 Thread가 공유)의 ArrayList에 추가하여 Heap Memory 부족해지는 것을 관찰 Runtime Data Area HeapOom.jsp %@ page language=java contentType=text/html; charset=UTF-8 pageEncoding=UTF-8% %@ page import=java.util.*% %@ page import=com.jadecross.troubleshoot.oom.heap.Member% Heap 메모리 부족 데모 % /* * Http 요청 1건마다 Member객체를 ArrayList에 추가 */ ArrayListMember members; members = (ArrayListMember) application.getAttribute(members); if (members == null) { members = new ArrayListMember(); application.setAttribute(members, members); } members.add(new Member()); % Member.java public class Member implements Serializable { public String name; public String age; public String sex; public String address; public Member() { this.name = name_ + UUID.randomUUID().toString(); this.age = age_ + UUID.randomUUID().toString(); this.sex = sex_ + UUID.randomUUID().toString(); this.address = address_ + UUID.randomUUID().toString(); } }
  • 113. 113 LAB) java.lang.OutOfMemoryError: Java heap space (2/5) Runtime Data Area ① STS 실행후 Tomcat v7.0 서버 실행 [root@jvmedu ~]# sts ② visualvm을 실행하고 visualgc 플러그인 설치  Applications 뷰에서 Local  Tomcat 더블 클릭  Visual GC 탭 클릭 [root@jvmedu ~]# visualvm ③ “System Monitor”를 실행하고 Resources 탭을 클릭하여 메모리 상황 관찰 [root@jvmedu ~]# gnome-system-monitor Permgen
  • 114. 114 LAB) java.lang.OutOfMemoryError: Java heap space (3/5) Runtime Data Area ④ jadeedu_jvmswjava_toolapache-jmeter-5.4.1bin 폴더 하위의 jmeter.bat 파일 실행 ⑤ 부하스크립트 파일 오픈 후 “UTG05_Heap OOM” Thread Group을 Enable한 후 부하를 발생시키고 Heap 메모리 관찰  스크립트 파일 : jadeedu_jvmswjava_toolapache-jmeter-5.4.1jmxJvmTroubleshoot.jmx  Enable Thread Group : UTG05_Heap OOM 부하 발생 7080 192.168.56.96
  • 115. 115 LAB) java.lang.OutOfMemoryError: Java heap space (4/5) Runtime Data Area
  • 116. 116 LAB) java.lang.OutOfMemoryError: Java heap space (5/5) Runtime Data Area