EC2 instance type: c5.2xlarge
AMI: Ubuntu 20.04
대상 프로젝트: https://github.com/Moojun/JCodeLib_SELAB_IJM
기존에는 EC2와 RDS를 사용하려고 했으나 어차피 프로젝트를 실행시켜 결과를 db에 저장하는 목적이므로, AWS Markertplace에서 검색하다 보면 Linux + MySQL 이미지가 같이 설치되어 있는 인스턴스를 사용하려고 하였다.
하지만 뭔가 잘 되지 않아서, 그냥 EC2 생성하고 거기에 mysql을 직접 설치하기로 결정함.
1. EC2에 mysql 설치
sudo apt-get update
sudo apt-get install mysql-server
# install check
mysql --version
그 외에는 생략. 나중에 필요하면 검색하기
2. java.lang.OutOfMemoryError: Java heap space
오류상황
- Neo4j 프로젝트를 돌리는 상황에서, heap space 용량 초과로 인한 실행 오류 발생
오류가 발생한 부분 소스 코드
// Prepare files.
List<String> fileInfo = new ArrayList<>();
PreparedStatement fileSel = con.prepareStatement(
" select c.commit_id commit_id, c.old_commit old_commit, c.new_commit new_commit, " +
" f.file_path file_path, f.file_id file_id " +
" from commits c, files f where c.commit_id = f.commit_id and c.project_name = '" + project + "'" +
" and c.merged_commit_status != 'T' " +
" order by file_id, commit_id ");
ResultSet fileRS = fileSel.executeQuery();
while (fileRS.next()) {
String str = String.join(",",
String.valueOf(fileRS.getInt("commit_id")),
fileRS.getString("old_commit"),
fileRS.getString("new_commit"),
fileRS.getString("file_path"),
String.valueOf(fileRS.getInt("file_id")));
fileInfo.add(str);
}
시도 1: 소스 코드 수정
String -> StringBuilder로 코드 변경
// Prepare files.
List<String> fileInfo = new ArrayList<>();
PreparedStatement fileSel = con.prepareStatement(
" select c.commit_id commit_id, c.old_commit old_commit, c.new_commit new_commit, " +
" f.file_path file_path, f.file_id file_id " +
" from commits c, files f where c.commit_id = f.commit_id and c.project_name = '" + project + "'" +
" and c.merged_commit_status != 'T' " +
" order by file_id, commit_id ");
ResultSet fileRS = fileSel.executeQuery();
while (fileRS.next()) {
StringBuilder sb = new StringBuilder();
sb.append(fileRS.getInt("commit_id")).append(",")
.append(fileRS.getString("old_commit")).append(",")
.append(fileRS.getString("new_commit")).append(",")
.append(fileRS.getString("file_path")).append(",")
.append(fileRS.getInt("file_id"));
fileInfo.add(sb.toString());
sb.setLength(0);
}
결과: Java heap space error
ArrrayList 선언 시 크기를 미리 지정
- Set Initial Capacity: When creating an ArrayList, you can specify an initial capacity that matches your expected number of elements. By setting an appropriate initial capacity upfront, you can avoid frequent resizing of the underlying array, which can save memory and improve performance.
- 코드 내에 fileInfo size는 7,078,601이므로, ArrayList 초기 사이즈를 7,079,000으로 설정
결과: Java heap space error
시도 2: EBS Volume 용량 추가
이 부분은 heap space error와 관련이 없다.
- 현재 110 GiB가 /(root) 용량으로 지정되어 있으며, EBS Volume 하나를 더 생성한 뒤(용량 600 GiB) EC2에 Attach. 이후 해당 용량 /backup 으로 mount. https://jenakim47.tistory.com/68
- 여전히 heap space error.
시도 3: Jvm heap memory 설정
- 현재 서버에는 java 11이 설치되어 있다.
- 아래 명령어로 heapSize 확인
java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|metaspacesize|version'
InitialHeapSize: 약 0.24 GiB, MaxHeapSzie: 약 3.79 GiB (단위: bytes로 예상)
∴ 결론은, 시도 2의 EBS volume 용량 문제가 아닌, 코드를 실행하는 과정에서 MaxHeapSize를 초과하여java.lang.OutOfMemoryError: Java heap space 오류가 발생하였다.
오라클 java 문서(http://www.oracle.com/technetwork/java/ergo5-140223.html) 에 따르면,
jvm을 server class로 실행하면 초기 heap size는 메모리의 1/64 이고, 최대 heap size는 1/4까지 늘어난다고 한다.
- 이에 따르면, 현재 ec2 instance의 RAM은 16 GiB이니, 약 1/4인 3.79 GiB가 max heap size.
인스턴스를 r4.2xlarge로 변경하였으며, max heap size를 32g로 변경함.
max heap size 변경 참고: https://medium.com/@hwimalasiri/how-to-increase-maximum-heap-size-of-jvm-in-ubuntu-e836b15284eb
sudo su
vi /etc/profile
# 아래 내용을 맨 위에 작성
export _JAVA_OPTIONS=-Xmx32g
# :wq!
source /etc/profile
'Amazon Web Services(AWS)' 카테고리의 다른 글
AWS] Next.js Spring Boot 도메인 연결 및 배포 (0) | 2023.06.21 |
---|---|
AWS] Route53 기초 (0) | 2023.06.21 |