1. 예외처리
1-1. 에러(error) vs 예외(exception)
자바에서는 애플리케이션 실행 시 발생할 수 있는 오류를 '에러(error)'와 '예외(exception)' 두 가지로 구분합니다.
에러는 메모리 부족, 스택오버플로우와 같이 발생하게 되면 복구할 수 없는 심각한 오류이고, 예외는 발생하더라도 수습할 수 있을 정도의 비교적 덜 심각한 오류입니다.
에러는 발생 시 막을 방도가 없지만, 예외는 프로그래머가 예외처리를 통해서 비정상종료를 막을 수 있는 것이죠.
1-2. 예외 클래스의 구조
Throwable 클래스를 상속 받는 클래스는 Error와 Exception이 있는데 모든 예외의 최고 상위 클래스는 당연히 Execption 입니다.
Error 의 경우 애플리케이션 레벨이 아닌 시스템 레벨의 심각한 영향을 주기 때문에 시스템에 변화를 주어 문제를 처리해야 하는 경우가 일반적입니다.
하지만 Exception은 개발자가 충분히 로직을 추가하여 처리할 수 있는 부분입니다.
1-3. Checked Exception과 Unchecked Exception 차이
위 그림 처럼 두 개 예외의 차이점은 처리여부입니다.
Checked Exception은 반드시 소스 코드내에서 예외를 처리해야만 실행단계로 넘어갑니다.
즉, 컴파일 단계에서 확인을 하기 때문에 반드시 예외처리를 구현한다(Check한다)라는 조건이 붙은 것이죠.
대표적으로는
- IOException
- SqlException
이 존재합니다.
public class CheckedException {
public static void main(String[] args)
{
try
{
// Exception 클래스로 예외를 실행시킨다.
throw new Exception();
} catch (Exception e)
{
// Checked Exception 이므로 예외처리를 해주는데 해주지 않으면 컴파일 실패
System.out.println("Exception");
}
}
}
Unchecked Exception은 반드시라는 조건이 없기 때문에 (Unchecked한다) 라는 조건이 붙은것이고,
실행 단계에서 발생 할 수 있는 모든 예외들을 말합니다.
특징으로는 프로그래머의 실수로 의해서 발생할 수 있는 예외라고 이해하시면 좋겠네요 🙂
대표적으로는
- NullPointerException
- IllegalArgumentException
- IndexOutOfBoundException
이 존재합니다.
public class ExceptionEx1 {
public static void main(String[] args)
{
// 에러가 발생하지만 컴파일은 가능하다.
throw new RuntimeException();
}
}
1-4. 예외 처리 방법
1. try-catch 블록을 사용한 예외 처리
- try 블록 안에서 예외가 발생할 수 있는 코드를 작성합니다.
- catch 블록은 try 블록에서 발생한 예외를 처리하는 부분입니다.
- catch 블록은 예외 타입에 따라 여러 개를 작성할 수 있으며, 발생한 예외와 일치하는 catch 블록이 실행됩니다.
- finally 블록은 선택적으로 작성할 수 있으며, 예외 발생 여부와 상관없이 항상 실행됩니다.
try {
// 예외가 발생할 수 있는 코드
} catch (예외 타입1 변수명1) {
// 예외 처리 코드
} catch (예외 타입2 변수명2) {
// 예외 처리 코드
} finally {
// 항상 실행되는 코드 (선택적)
}
2. throws를 사용한 예외 처리
- 메서드 선언부에 throws 키워드를 사용하여 메서드에서 발생할 수 있는 예외를 명시합니다.
- 메서드를 호출하는 곳에서 예외를 처리하도록 할 수 있습니다.
void 메서드명() throws 예외타입1, 예외타입2 {
// 예외가 발생할 수 있는 코드
}
3. 사용자 정의 예외 처리
- 사용자 정의 예외 클래스
class MyException extends Exception {
public MyException() {
super("사용자 정의 예외가 발생했습니다.");
}
public MyException(String message) {
super(message);
}
}
위의 예제에서 MyException 클래스는 Exception 클래스를 상속받아 사용자 정의 예외 클래스를 만들었습니다. 생성자를 통해 예외 메시지를 설정할 수 있습니다.
- 사용자 정의 예외 클래스를 사용하는 코드
public class Main {
public static void main(String[] args) {
try {
throwException();
} catch (MyException e) {
System.out.println(e.getMessage());
}
}
public static void throwException() throws MyException {
throw new MyException("사용자 정의 예외를 발생시킵니다.");
}
}
위의 예제에서 throwException 메서드에서 **MyException**을 발생시키고, main 메서드에서 해당 예외를 처리합니다. 실행 결과는 "사용자 정의 예외를 발생시킵니다."라는 메시지가 출력됩니다.
이와 같이 사용자 정의 예외 클래스를 만들어 예외 상황에 대한 적절한 처리를 할 수 있습니다. 사용자 정의 예외 클래스를 만들 때는 예외의 특정 상황을 잘 표현하고 처리하기 위한 메시지와 추가적인 기능을 구현하는 것이 좋습니다.
2. JVM 동작방식 및 구조
2-1. 동작 과정
- 자바 언어로 작성된 애플리케이션을 실행하면 JVM은 OS로부터 메모리를 할당합니다.
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일합니다.
- Class Loader를 통해 JVM Runtime Data Area로 로딩합니다.
- Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석합니다.
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어집니다.
2-2. RunTime Data Area
자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역입니다.
모든 스레드가 공유해서 사용 (GC의 대상)
- 힙 영역 (Heap Area)
- new 키워드로 생성된 객체와 배열이 생성되는 영역입니다.
- 주기적으로 GC가 제거하는 영역입니다.
- 메서드 영역(Method Area)
- 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메서드 정보 등이 생성되는 영역입니다.
스레드(Thread) 마다 하나씩 생성
- 스택 영역(Stack Area)
- 지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역입니다.
- PC 레지스터 (PC Register)
- Thread가 생성될 때마다 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역입니다.
- 네이티브 메서드 스택(Native Method Stack)
- 자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 네이티브 코드를 실행할 때 사용되는 메모리 영역입니다.
3. 에러(error) vs 예외(exception)
자바에서는 애플리케이션 실행 시 발생할 수 있는 오류를 '에러(error)'와 '예외(exception)' 두 가지로 구분합니다.
에러는 메모리 부족, 스택오버플로우와 같이 발생하게 되면 복구할 수 없는 심각한 오류이고, 예외는 발생하더라도 수습할 수 있을 정도의 비교적 덜 심각한 오류입니다.
에러는 발생 시 막을 방도가 없지만, 예외는 프로그래머가 예외처리를 통해서 비정상종료를 막을 수 있는 것이죠.
3-1. 예외 클래스의 구조
Throwable 클래스를 상속 받는 클래스는 Error와 Exception이 있는데 모든 예외의 최고 상위 클래스는 당연히 Execption 입니다.
Error 의 경우 애플리케이션 레벨이 아닌 시스템 레벨의 심각한 영향을 주기 때문에 시스템에 변화를 주어 문제를 처리해야 하는 경우가 일반적입니다.
하지만 Exception은 개발자가 충분히 로직을 추가하여 처리할 수 있는 부분입니다.
Checked Exception과 Unchecked Exception 차이
위 그림 처럼 두 개 예외의 차이점은 처리여부입니다.
Checked Exception은 반드시 소스 코드내에서 예외를 처리해야만 실행단계로 넘어갑니다.
즉, 컴파일 단계에서 확인을 하기 때문에 반드시 예외처리를 구현한다(Check한다)라는 조건이 붙은 것이죠.
대표적으로는
- IOException
- SqlException
이 존재합니다.
public class CheckedException {
public static void main(String[] args)
{
try
{
// Exception 클래스로 예외를 실행시킨다.
throw new Exception();
} catch (Exception e)
{
// Checked Exception 이므로 예외처리를 해주는데 해주지 않으면 컴파일 실패
System.out.println("Exception");
}
}
}
Unchecked Exception은 반드시라는 조건이 없기 때문에 (Unchecked한다) 라는 조건이 붙은것이고,
실행 단계에서 발생 할 수 있는 모든 예외들을 말합니다.
특징으로는 프로그래머의 실수로 의해서 발생할 수 있는 예외라고 이해하시면 좋겠네요 🙂
대표적으로는
- NullPointerException
- IllegalArgumentException
- IndexOutOfBoundException
이 존재합니다.
public class ExceptionEx1 {
public static void main(String[] args)
{
// 에러가 발생하지만 컴파일은 가능하다.
throw new RuntimeException();
}
}
3-2. 예외 처리 방법
1. try-catch 블록을 사용한 예외 처리
- try 블록 안에서 예외가 발생할 수 있는 코드를 작성합니다.
- catch 블록은 try 블록에서 발생한 예외를 처리하는 부분입니다.
- catch 블록은 예외 타입에 따라 여러 개를 작성할 수 있으며, 발생한 예외와 일치하는 catch 블록이 실행됩니다.
- finally 블록은 선택적으로 작성할 수 있으며, 예외 발생 여부와 상관없이 항상 실행됩니다.
try {
// 예외가 발생할 수 있는 코드
} catch (예외 타입1 변수명1) {
// 예외 처리 코드
} catch (예외 타입2 변수명2) {
// 예외 처리 코드
} finally {
// 항상 실행되는 코드 (선택적)
}
2. throws를 사용한 예외 처리
- 메서드 선언부에 throws 키워드를 사용하여 메서드에서 발생할 수 있는 예외를 명시합니다.
- 메서드를 호출하는 곳에서 예외를 처리하도록 할 수 있습니다.
void 메서드명() throws 예외타입1, 예외타입2 {
// 예외가 발생할 수 있는 코드
}
3. 사용자 정의 예외 처리
- 사용자 정의 예외 클래스
class MyException extends Exception {
public MyException() {
super("사용자 정의 예외가 발생했습니다.");
}
public MyException(String message) {
super(message);
}
}
위의 예제에서 MyException 클래스는 Exception 클래스를 상속받아 사용자 정의 예외 클래스를 만들었습니다. 생성자를 통해 예외 메시지를 설정할 수 있습니다.
- 사용자 정의 예외 클래스를 사용하는 코드
public class Main {
public static void main(String[] args) {
try {
throwException();
} catch (MyException e) {
System.out.println(e.getMessage());
}
}
public static void throwException() throws MyException {
throw new MyException("사용자 정의 예외를 발생시킵니다.");
}
}
위의 예제에서 throwException 메서드에서 **MyException**을 발생시키고, main 메서드에서 해당 예외를 처리합니다. 실행 결과는 "사용자 정의 예외를 발생시킵니다."라는 메시지가 출력됩니다.
이와 같이 사용자 정의 예외 클래스를 만들어 예외 상황에 대한 적절한 처리를 할 수 있습니다. 사용자 정의 예외 클래스를 만들 때는 예외의 특정 상황을 잘 표현하고 처리하기 위한 메시지와 추가적인 기능을 구현하는 것이 좋습니다.
4. JVM 동작방식 및 구조
4-1. 동작 과정
- 자바 언어로 작성된 애플리케이션을 실행하면 JVM은 OS로부터 메모리를 할당합니다.
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일합니다.
- Class Loader를 통해 JVM Runtime Data Area로 로딩합니다.
- Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석합니다.
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어집니다.
4-2. RunTime Data Area
자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역입니다.
모든 스레드가 공유해서 사용 (GC의 대상)
- 힙 영역 (Heap Area)
- new 키워드로 생성된 객체와 배열이 생성되는 영역입니다.
- 주기적으로 GC가 제거하는 영역입니다.
- 메서드 영역(Method Area)
- 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메서드 정보 등이 생성되는 영역입니다.
스레드(Thread) 마다 하나씩 생성
- 스택 영역(Stack Area)
- 지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역입니다.
- PC 레지스터 (PC Register)
- Thread가 생성될 때마다 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역입니다.
- 네이티브 메서드 스택(Native Method Stack)
- 자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 네이티브 코드를 실행할 때 사용되는 메모리 영역입니다.
'Java' 카테고리의 다른 글
[Java] 생성자 this(), 참조변수 this (0) | 2023.05.31 |
---|---|
[Java] 오버로딩, 오버라이딩 (0) | 2023.05.30 |
[Java] static 메서드와 인스턴스 메서드 (0) | 2023.05.30 |
[Java] 컬렉션과 제네릭 (0) | 2023.05.30 |
[Java] 추상클래스와 인터페이스 (0) | 2023.05.30 |