∘ 재사용성과 유지보수가 좋다. (캡슐화, 상속, 다형성, 추상화)
∘ OS에 독립적이다. (JVM)
∘ 자동 메모리 관리 (GC)
∘ 보안성이 뛰어나다.
∘ 멀티스레드 & 동적 로딩 지원
[ Object-Oriented Programming : OOP ]
[ 객체지향 프로그래밍 ]
∘ 데이터를 추상화시켜 상태(변수)와 행위(함수)를 가진 객체를 만들고 객체간 상호작용을 통해 로직을 구성
∘ 여러 개의 독립된 단위(객체)들의 모임으로 파악하여 객체들이 메시지를 주고받고, 데이터를 처리(협력)
∘ 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프 트웨어 개발에 많이 사용
∘ 장점
ⅰ. 코드의 재사용성이 높다.
⇨ 만들어진 클래스를 가져와 사용할 수 있고 상속을 통해 확장이 가능하다.
ⅱ. 유지보수가 쉽다.
⇨ 수정해야 할 부분이 클래스 내부에 변수나 메서드로 존재하기에 해당 부분만 수정하면 된다.
ⅲ. 대형 프로젝트에 적합하다.
⇨ 클래스 단위로 모듈화하여 개발이 가능하다.
∘ 단점
ⅰ. 처리속도가 느리다.
ⅱ. 객체가 많으면 용량이 커진다.
ⅲ. 설계시 많은 노력과 시간이 필요하다.
추상화
∘ 인터페이스로 클래스들의 공통 특성을 묶어 표현하는 것
∘ 불필요한 정보는 숨기고 필요한 정보만을 표현할 수 있다.
캡슐화(정보 은닉)
∘ 속성(멤버변수)과 기능(메서드)을 캡슐(클래스)에 넣어 모으고 분류
∘ 장점 : 재활용 & 정보은닉
상속
∘ 자식 클래스가 부모 클래스의 특성과 기능을 물려받아 사용 및 수정
∘ 코드 수정 & 클래스의 재사용 용이
다형성
∘ 오버라이딩, 오버로딩 가능
∘ 역할 & 구현으로 구분 ⇨ 단순해지고, 유연해지며 변경도 편리
∘ 유연하고 변경 용이 & 확장 가능한 설계 가능
[ 객체지향 설계 원칙 SOLID ]
1. SRP 단일 책임 원칙 [ Single Responsibility Principle ]
• 한 클래스는 하나의 책임만 가져야 한다.
• 책임은 상황에 따라 다를 수 있다.
• 중요한 기준은 변경 : 변경이 있을 때 파급 효과가 적으면 SRP를 잘 따른것
ex) UI 변경, 객체의 생성과 사용을 분리
2. OCP 개방-폐쇄 원칙 [ Open/Closed Principle ]
• 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다
• 다형성을 활용 : 인터페이스를 구현한 새로운 클래스에 새로운 기능을 구현
• 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요
3. LSP 리스코프 치환 원칙 [ Liskov Substitution Principle ]
• 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
• 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것
• 다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요
ex) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능
뒤로 가게 구현하면 LSP 위반, 느리더라도 앞으로 가야함
4. ISP 인터페이스 분리 원칙 [ Interface Segregation Principle ]
• 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다
• Car 인터페이스 -> 운전, 정비 인터페이스로 분리
• User 클라이언트 -> 운전자, 정비사 클라이언트로 분리
• 분리하면 임의의 인터페이스 자체가 변해도 특정 클라이언트에 영향을 주지 않음
• 인터페이스가 명확해지고, 대체 가능성이 높아진다.
5. DIP 의존관계 역전 원칙 [ Dependency Inversion Principle ]
• 추상화에 의존해야지, 구체화에 의존하면 안된다.
⇨ 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻
• 의존성 주입(DI)은 이 원칙을 따르는 방법 중 하나
• 클라이언트가 인터페이스에 의존해야 유연하게 구현체 변경 가능
[ JVM : Java Virtual Machine ]
∘ Java Byte Code를 OS에 맞게 해석하는 역할
∘ 이후 실행과정 속 필요에 따라 스레드 동기화, GC와 같은 메모리 관리작업 수행
∘ 어떤 기기상에서 실행되고 있는 프로세스에 대한 자원을 대표하고 통제하는 서버
∘ 기능
① 자바 프로그램이 어느 기기나 OS 상에서도 실행되도록 함
② 프로그램 메모리를 관리&최적화
∘ 구성
① Class Loader
∘ Runtime 시점에 클래스를 로딩
∘ 클래스의 인스턴스 생성시 메모리에 인스턴스 로드
② Runtime Data Areas ( JVM Memory )
∘ JVM이 프로그램을 수행하기 위해 OS로부터 할당받은 메모리 공간
ⅰ. PC Register ⇨ Thread별로 현재 수행중인 JVM의 주소를 지니다.
ⅱ. JVM Stack ⇨ Thread별로 변수 / 메서드 저장
ⅲ. Native Method Stack⇨ 실제 실행할 수 있는 기계어로 작성된, 프로그램을 실행시키는 영역
ⅳ. Method ⇨ JVM이 시작할 때 생성되어 정적변수 / 메서드 코드 등을 보관
ⅴ. Heap ⇨ 런타임시 동적할당되는 데이터 저장
③ Excution Engine
∘ Class Loader에 의해 JVM 내의 Runtime Data Areas에 배치된 Byte Code를 실행하는 영역
[ GC : Garbage Collection ]
∘ 특정 기능 수행이 완료되어 더이상 필요없는 객체를 효과적으로 처리(제거)하는 작업
∘ 자바에서는 메모리를 GC를 통하여 관리하기 때문에, 개발자가 메모리를 처리하기 위한 로직을 만들 필요가 없다.
∘ 자바 메모리 영역에서 Heap 영역을 관리
∘ OOM Error : GC를 해도 더 이상 사용가능한 메모리 영역이 없는데 메모리를 할당하고자 할 때 발생하는 오류
∘ 영역
① Young : 생성된지 얼마 안된 객체들이 저장되는 장소, Minor GC
② Old : 오랫동안 사용중인 객체들이 저장되는 장소, Full GC
③ MetaSpace(Perm) : 클래스 & 메타 데이터가 저장되는 영역
∘ Garbage Collection : Minor GC, Full GC
∘ Garbage Collector
① Serial Collector : Minor GC와 Full GC가 하나의 스레드에서 이루어지는 알고리즘
② Parallel : Serial Collector를 병렬화한 알고리즘. 멀티CPU에서 성능이 좋다.
③ Concurrent Mark Sweep(CMS) : Stop the World 처리시간을 최소화하는데 초점을 맞춘 방식
④ Garbage-First (G1) : 대용량 메모리가 있는 멀티 프로세서 시스템용
※ STW (Stop The World)
∘ GC를 실행하기위해 JVM이 애플리케이션 실행을 멈추는 것
∘ GC 튜닝이란 STW 시간을 줄이는 것이다.
[ Java 컴파일 과정 ]
① 개발자가 자바 소스코드(.java) 작성
② 자바 컴파일러가 소스파일(.java)을 컴파일 ⇨ 바이트코드(.class) 파일 생성
바이트 코드 : 각 명령어가 1바이트 크기의 명령코드와 추가 피연산자로 이루어짐
③ 컴파일된 바이트코드를 JVM 클래스로더에게 전달
④ 클래스로더는 동적로딩을 통해 클래스들을 로딩&링크하여 JVM 메모리 (런타임 데이터 영역) 에 올린다.
⑤ 실행 엔진이 JVM 메모리에 올라온 바이트코드들을 명령어 단위로 하나씩 가져와 실행
5-1. 인터프리터 : 바이트코드 명령어를 하나씩 읽어서 해석하고 실행 ( 하나하나는 빠르지만 전체적으로 느림 )
5-2. JIT Compiler : 바이트코드 전체를 컴파일하여 바이너리코드로 변경하고 직접 실행시키는 방식 ( 빠르다. )
[ Java 메모리 구조 ]
① Class ( Method )
∘ 클래스, 클래스 변수(static Variable), 메서드
② Stack
∘ 메소드 호출 정보(스택프레임)
∘ 메소드 호출시 관계되는 멤버변수 & 지역변수
∘ 스레드마다 할당
∘ 메소드 호출이 완료되면 소멸
∘ 높은주소 → 낮은주소 순으로 할당
③ Heap
∘ 멤버 변수, new 키워드를 통해 생성된 인스턴스
∘ 낮은주소 → 높은주소 순으로 할당
[ 변수 ]
Class Variable {
static int classValue; // 클래스 변수
int instanceValue; // 인스턴스 변수
void method() {
int localValue; // 지역 변수
}
}
클래스 변수
∘ static 키워드가 붙은 변수
∘ 해당 클래스의 모든 인스턴스가 공통된 값을 공유하게 된다.
따라서 한 클래스의 모든 인스턴스가 공통적인 값을 가져야할 때, 클래스 변수로 선언한다.
∘ 클래스가 로딩될때 생성되어 종료될때까지 유지, public을 붙이면 전역변수가 된다.
∘ 인스턴스 생성 없이 접근할 수 있으므로 클래스명.변수명 을 통해 접근할 수 있다.
∘ Method Area
인스턴스 변수
∘ 인스턴스가 생성될 때 생성
따라서 인스턴스 변수를 사용하기 전에 먼저 객체를 생성해야 한다.
∘ 인스턴스 변수는 독립적인 저장공간을 가지므로 인스턴스 별로 다른 값을 가질 수 있다.
∘ Heap Area
지역 변수
∘ 메소드 내에 선언되며 메소드 내에서만 사용할 수 있는 변수이다.
∘ 메소드가 실행될 때, 메모리를 할당받으며 메소드가 끝나면 소멸되어 사용할 수 없게 된다.
∘ Stack Area
[ Java Type ]
기본형 타입
∘ boolean, char, byte, short, int, long, float, double (8개)
∘ 비객체 타입, null 불가능
∘ NULL을 넣고 싶다면 Wrapper class 활용
∘ Stack Area에 저장
참조형 타입
∘ class, interface, array, enum
∘ Heap Memory 영역에 생성된 객체의 주소값을 참조
∘ JAVA 최상인 java.lang.Object 클래스를 상속하는 모든 클래스
∘ new로 인해 생성되어 Heap Area에 저장, GC에 의해 관리
∘ 비교시 equals( ) 사용
[ Casting ]
∘ 변수가 원하는 정보를 다 갖고있는것
∘ 목적 : 다형성 + 상속
ex) int a = 0.1 ⇨ 0.1은 int로 될 정보 또한 지니고 있다. ( upCasting )
but int b = (int)true ⇨ boolean을 int로 캐스트 불가능 ( downCasting )
묵시적 형변환
∘ 캐스팅이 자동으로 발생 (UpCasting)
∘ Parent p = new Child();
⇨ Parent를 상속받은 Child는 Parent의 속성을 포함하고 있으므로 명시할 필요가 없다.
명시적 형변환
∘ 캐스팅할 내용을 적어줘야 하는 경우 (DownCasting)
∘ Parent p = new Child();
Child c = (Child) p;
[ Call By Value & Call By Reference ]
Call By Value : 값에 의한 호출
∘ 함수가 호출될 때 메모리 공간 안에서 함수를 위한 임시공간 생성
∘ 변수값을 복사해서 전달받음 ( Local Value 속서을 지닌다 )
⇨ 함수 안 인자값이 변경되어도 외부 변수값은 변경되지 않음
class CallByValue {
public static void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
public static void main(String[] args)
{
int a = 10;
int b = 20;
System.out.println("swap() 호출 전 : a = " + a + ", b = " + b);
// swap() 호출 전 : a = 10, b = 20
swap(a, b);
System.out.println("swap() 호출 후 : a = " + a + ", b = " + b);
// swap() 호출 후 : a = 10, b = 20
}
}
swap() 메서드 호출시 a와 b의 메모리 ( 0x0001, 0x0005 )에 담겨 있던 값만이 복사되어 swap 메서드의 매개변수(x, y)에 담긴다. swap() 메서드가 수행되는 동안 swap() 내부에서 새롭게 생성된 x, y값을 변경하기 때문에 수행 후에도 결과는 변하지 않는다.
Call By Reference : 참조에 의한 호출
∘ 함수 호출시 인자로 전달되는 변수의 레퍼런스를 전달
∘ 함수 안에서 인자 값이 변경되면 객체 값도 변경됨
Class CallByReference {
int value;
CallByReference(int value) {
this.value = value;
}
public static void swap(CallByReference x, CallByReference y) {
int temp = x.value;
x.value = y.value;
y.value = temp;
}
public static void main(String[] args) {
CallByReference a = new CallByReference(10);
CallByReference b = new CallByReference(20);
System.out.println("swap() 호출 전 : a = " + a.value + ", b = " + b.value);
// swap() 호출 전 : a = 10, b = 20
swap(a, b);
System.out.println("swap() 호출 전 : a = " + a.value + ", b = " + b.value);
// swap() 호출 후 : a = 20, b = 10
}
}
객체 a와 b 에는 Heap Memory 영역에 생성된 객체의 주소값이 있다. 함수의 매개변수로 a와 b를 사용한다면 객체 a와 b의 주소값을 복사한 새로운 객체를 함수 내에서 사용한다. 이 함수 내에서 x와 y를 다른 객체로 재정의하지 않는 한 x와 y는 a, b와 같은 주소값을 가진다. 따라서 객체 x, y 안의 변수를 변경하게 되면 주소값 내의 변수를 변경하는 것이므로 마치 call by reference와 같아보인다.
하지만 실제로는 객체 a,b의 주소값을 복사하여 사용하는 것이므로 자바는 Call By Value이다.
∘ 자바는 항상 Call By Value로 값을 넘긴다.
∘ 메모리에 저장된 주소를 보내는 것도 물리적 관점으로 값으로 볼 수 있기 때문
∘ 객체의 참조값을 직접 바꾼것이 아니라 객체의 참조값을 통해 멤버변수에 접근하여 실제 값을 바꾼것
∘ 객체를 매개변수로 전달했을때 객체 안의 매개변수 값을 변경하면 주소 안의 실제 값을 바꿀 수 있다.
( 나머지는 불가능 )
[ Java의 String ]
∘ 불변 객체 (Immutable) 이므로 동기화를 신경쓰지 않아도 된다.
∘ 문자열 연산시 새로운 객체를 만드는 오버헤드 발생
∘ 문자열 연산이 적고 조회가 많은 상황에 쓰기 좋다.
∘ GC로 제거되어야 한다.
[ StringBuilder & StringBuffer ]
∘ Mutable 객체
∘ 문자열 연산 시 처음 만든 객체를 이용해 연산하고 크기를 변경시켜 문자열을 변경한다.
∘ 문자열 연산이 자주 발생하는 상황에 쓰기 좋다.
∘ 문자열 연산시 크기를 변경시킨다.
StringBuilder
∘ Thread Unsafe
∘ 동기화를 고려하지 않는 싱글스레드 환경에 적합
StirngBuffer
∘ Thread Safe
∘ 동기화가 필요한 멀티스레드 환경에 적합
[ == equals ]
== : 비교하고자 하는 대상의 주소값 비교
equals() : 비교하고자 하는 대상의 값 비교
[ Collection ]
∘ List, Map, Set 인터페이스를 기준으로 여러 구현체 존재 ( Stack, Queue etc. )
∘ 동적배열의 개념
∘ 다수의 Data를 다르는데 표준화된 클래스를 제공해주기 때문에 편하게 사용할 수 있음
∘ 객체를 보관하기 위한 공간을 미리 정하지 않아도 되므로 객체 수를 동적으로 정할 수 있다.
List
∘ ArrayList, LinkedList, Stack, Queue
∘ 중복 O, 저장공간 가변적
Map
∘ HashMap, LinkedHashMap (key순서보장)
∘ key 중복 X
∘ key-value 쌍으로 이루어진 자료구조
∘ 데이터에 접근하기 위해 index가 아닌 key로 접근
Set
∘ HashSet (무작위 값), LinkedHashSet (순서보장), TreeSet(자동정렬)
∘ 집합, 중복 X
[ Access Modifier ]
∘ 변수 or 메서드 접근 범위를 설정하는 Java 예약어
∘ public : 어떤 클래스에서도 접근 가능
∘ protected : 해당 패키지&클래스를 상속받은 외부 패키지의 클래스에서 접근 가능
∘ package(defalut) : 클래스가 정의된 해당 패키지에서만 접근 가능
∘ private : 해당 클래스 내에서만 접근 가능
[ final ]
∘ final 클래스 : 다른 클래스에서 상속 불가능
∘ final 변수 : 변하지 않는 상수값이 되어 새롭게 할당 불가능
∘ final 메서드 : 다른 메소드에서 오버라이딩 불가능
[ static ]
∘ 프로그램이 시작할 때 Stack Area에 메모리가 할당되어 프로그램이 종료될때 해체되는 변수
∘ static 클래스 : 객체를 생성하지 않고도 변수&함수 사용 가능
∘ static 변수 : 객체들이 다같이 공유하는 데이터
∘ static 메서드 : 객체들의 데이터와 관계없는 완벽하게 공통적인 로직을 정의할 때 사용
인스턴스변수나 객체의 함수를 사용할 수 없다
[ Overriding vs. Overloading ]
∘ Overriding : 상위 클래스/인터페이스에 존재하는 메소드를 하위클래스에서 재정의하는 것
∘ Overloading : 같은 이름과 return형의 함수를 다른 매게변수로 만들어 사용
[ 추상 클래스 ]
∘ 미완성 클래스(설계도)
∘ 혼자로써의 역할은 못하지만, 새로운 클래스의 부모 클래스로서의 의미를 갖는다.
∘ 일반 함수, 멤버 포함 가능 [ 차이점 ]
∘ 추상 메소드를 포함한다면 반드시 추상 클래스로 선언
∘ 인스턴스 생성 불가능 [ 공통점 ]
목적 : 자식클래스로 하여금 구현을 강제한다, 메소드의 동작은 자식클래스에게 위임한다.
[ 인터페이스 ]
∘ 기본 설계도
∘ 인터페이스를 구현하는 모든 클래스에 대해 특정 메소드가 반드시 존재하도록 강제
∘ 일종의 추상클래스지만 추상화 정도가 높아 일반메소드, 일반멤버변수를 가질 수 없다.
∘ 오직 추상메소드와 상수만을 가질 수 있다.
∘ 모든 멤버변수 : public static final 이어야 하며 생략가능
∘ 모든 메소드 : public abstract 이어야 하며 생략 가능
∘ 클래스에서 인터페이스 다중 상속 가능, 다중 구현 가능
∘ 장점 : 대규모 프로젝트 개발시 일관된 표준화 가능
∘ 클래스 작성 & 인터페이스 구현 동시에 진행 가능 ⇨ 개발시간↓
∘ 클래스간 관계를 인터페이스로 연결하면 클래스마다 독립적 프로그래밍 가능
목적 : 구현 객체가 같은 동작을 하는것을 보장하는것
[ 추상 클래스 vs 인터페이스 ]
추상클래스 | 인터페이스 |
∘ 클래스 o ∘ 추상메소드, 일반메소드, 일반멤버 가능 ∘ 다중 상속 불가능 ∘ 목적 - 상속을 받아 기능을 확장시키는 목적 - 공유의 목적 - 자식클래스에게 구현 강제화 |
∘ 클래스 x ∘ 추상메소드와 상수, default/static 메소드 ∘ 다중 구현 가능 ∘ 목적 : 구현 객체와 같은 동작을 보장하기 위해 사용 |
[ Wrapper Class ]
∘ 기본자료형 8가지에 대한 클래스 표현
∘ null을 사용해야 할때 사용하는 경우가 있음
∘ == 사용 대신 .intValue( ) 메소드를 통해 값을 가져와 비교해야 한다.
∘ 사용 이유
1. null을 사용해야 할때
2. Genereics( < > ) 에 넣어야 할때
3. String타입으로 변환하고자 할때
∘ Boxing (to Wrapper) , Unboxing (from Wrapper)
[ Generic ]
∘ 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입을 가질 수 있도록 하는것
∘ Collection 클래스에서 사용하는 것으로 컴파일 과정에서 타입체크를 해주는 기능
∘ Collection 내부에 들어온 값이 내가 원하는 값인지 별도로 로직처리를 구현할 필요가 없다.
∘ API 설계시 보다 명확한 의사전달 가능
class Generic<K, V> {
private K key;
private V value;
void set(K key, V value) {
this.key = key;
this.value = value;
}
void print() {
System.out.println(key + " : " + value);
}
}
public class Main {
public static void main(String[] args) {
Generic<String, Integer> generic = new Generic<>();
generic.set("TEN", 10);
generic.print(); // TEN : 10
Generic<Integer, String> generic2 = new Generic<>();
generic2.set(10, "TEN");
generic2.print(); // 10 : TEN
}
}
[ Annotation (@) ]
∘ 컴파일러에게 코드 문법 에러를 체크하도록 정보 제공
∘ 실행 시 특정 기능을 실행하도록 정보 제공
∘ built-in ano (@Override) , Meta ano , Custom ano
[ Reflection ]
∘ 자바에서 이미 로딩이 완료된 클래스 or 다른 클래스를 동적로딩하여
구체적인 타입을 몰라도 생성자, 멤버필드, 멤버메소드를 사용할 수 있는 기법
∘ 객체를 통해 클래스의 패키지정보, 접근지정자, 부모클래스, 어노테이션을 얻을 수 있음
∘ 컴파일 타임이 아니라 런타임에 동적으로 특정 클래스의 정보를 객체화하여 추출할 수 있는 기법
∘ 사용 목적 : Runtime중 다른 클래스를 동적로딩하여 접근할 필요가 있을때
∘ 주의 : private 멤버도 Field.setAccessible( ) 를 true로 지정하면 접근&조작이 가능해진다.
∘ JVM 최적화 수행 불가능 ⇨ 성능↓
[ Java Thread ]
∘ JDK에서 지원하는 java.lang.Thread 제공
∘ 생성방법
① Thread 클래스 이용
∘ Thread 클래스로부터 제공되는 run() 메소드를 오버라이딩해서 사용
public class ThreadX extends Thread {
public void run ( ) {
// 수행할 문장 기술
}
}
...
ThreadX TX = new ThreadX( );
TX.start( );
② Runnalbe 인터페이스를 구현해서 생성
∘ 현재 클래스가 이미 다른 클래스로부터 상속받고 있다면 Runnable인터페이스를 이용하여 스레드 생성
∘ Runnable Interface : JDK 라이브러리 인터페이스, run( ) 메소드만 정의되어 있다.
∘ run( ) 메소드가 종료되면 스레드는 종료
∘ 한번 종료한 스레드는 다시 시작할 수 없다.
∘ 한 스레드에서 다른 스레드를 강종 가능
public class RunnableX implements Runnable {
public void run ( ) {
// 인터럽트 예외처리 + 수행할 문장 기술
}
}
...
RunnableX RX = new RunnableX( );
Thread th = new Thread(RX);
th.start( );
∘ 스레드 상태 6가지
⇨ NEW(생성) / RUNNABLE(실행or준비완료) / WAITING(wait, 동기화) /
TIME_WAITING(sleep) / BLOCK(I/O작업) / TERMINATED(종료)
∘ 스레드 상태는 JVM에 의해 기록&관리
∘ wait( ) : 스레드가 lock을 가지고 있으면, lock 권한을 반납하고 대기하게 만든다.
∘ notify( ) : 대기상태인 스레드에게 다시 lock 권한을 부여하고 수행하게 한다.
[ Error vs Exception ]
Throwable 클래스
∘ 예외처리를 할 수 있는 최상위 클래스 ( Exception, Error가 상속받음 )
Error
∘ 컴파일 시 문법적인 오류
∘ 런타임 시 NullPoint 참조와 같은 오류 등으로 심각한 문제를 야기시켜 프로세스가 종료
⇨ OOM, StackOverflow 등 복구할 수 없는 심각한 오류
∘ OOM : JVM에서 설정된 메모리의 한계를 벗어난 상황
∘ Heap 사이즈 부족 / 너무 많은 class 로드 / 가용가능한 swap X / 큰 메모리의 native 메소드가 호출
∘ 해결 : dump 파일 분석, jvm 옵션 수정
Exception
∘ 동작 도중 예기치 않았던 이상 상태가 발생하여 수행중인 프로그램이 영향을 받는것
∘ 수습할 수 있는 비교적 덜 심각한 오류
∘ 예외가 주로 발생하는 원인
⇨ 사용자의 잘못된 입력, 잘못된 연산, 잘못된 로직, HW/Network 오작동, 시스템 과부하 etc.
∘ Checked Exception(예외처리 필수, 컴파일 불가) : RuntimeE, IOE, SQLE
∘ Unchecked Exception(런타임에 발생하는 예외) : RuntimeE 하위의 모든 예외 [ NullPointerE, IndexOutOfE etc... ]
[ Exception Handling ]
① try-catch를 이용하여 예외에 대한 최종적인 책임을 지고 처리
∘ try에는 위험한 로직이 들어가고 catch에는 예외발생시 수행할 로직이 들어간다.
∘ catch는 else if 처럼 여러개 사용 가능
∘ finally는 마지막에 실행하고 싶은 로직 ( 대표적으로 .close( ) )
② throws Exception을 이용하여 예외의 책임을 호출하는 쪽이 지도록 하는 방식