[Java] 6. static & GC & 예외처리

Kyunghwan Ko·2022년 9월 28일
0

Java

목록 보기
7/14

Tip

클래스 변수 = static 변수, 클래스 메서드 = static 메서드

static 변수

static 변수 = 정적 변수 = 클래스 변수 = 공용변수 = 전역변수

  • 객체를 생성하지 않고도 static 자원에 접근가능o
  • Java에서 static 키워드를 사용한다는 것은 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 것을 의미(GC관리x)
  • 클래스로더에 의해 클래스가 로더될 때 같이 static 영역(메서드 영역)에 올라간다.

⭐ Garbage Collection이란?

Java의 Garbage Collection(GC)은 Java 프로그램이 자동 메모리 관리를 수행하는 동작이다. Java 프로그램은 JVM(Java Virtual Machine)에서 실행할 수 있는 바이트코드(.class파일)로 컴파일된다. Java 프로그램이 JVM에서 실행될 때 프로그램에 할당된 힙 메모리에 객체를 생성하고 사용하게되는데, 이 과정에서 객체 중 더이상 사용하지 않은 객체가 생기게된다. 이때 Garbage Collector(GC)는 이러한 사용되지 않는 객체를 찾아 삭제하여 메모리를 확보한다.

즉, Garbege Collector는 자바 프로그램이 실행되는 동안 JVM안에서 자동으로 힙 메모리 영역을 관리하는 것, 주로 unused or unrefrenced object(=unreachable object)를 찾아내서 힙 메모리에서 삭제시킴으로써 메모리영역을 관리한다.

C언어를 이용하면 free()라는 함수를 통해서 직접 메모리를 해제해주어야한다. 그렇지 않으면 OutOfMemoryError를 만날 수 있다. 하지만 자바는 이런 과정을 GC를 통해 자동으로 관리해주어서 편리하다 :smile

unreachable object란?

Integer i = new Integer(4);
// 생성된 Integer객체는 참조변수 i에 의해 reachable하다.
i = null;
// i가 null을 참조하면서, Integer객체가 unreachable해졌다. 

static 변수의 접근방법

클래스 내부 접근

  • static 변수가 선언된 클래스 내에서는 이름만으로 직접 접근 가능

클래스 외부 접근

  • Access Modifier(private, protected 등)가 허용하는 범위에서 접근 가능
  • 클래스 또는 인스턴스의 이름을 통해 접근
class AccessWay{
	static int num; // default로 컴파일러서 0으로 초기화
}
public class HelloWorld{
	public staic void main(String[] args){
		AccessWay way = new AccessWay();
		way.num++;
		System.out.println(way.num); // 1
		AccessWay.num++;
		System.out.println(AccessWay.num); // 2
	}
}

활용예제1

현재 생성된 객체의 수를 유지하기 위해서 활용할 수 있다.

class InstCnt{
	static int instNum = 0; // 생성된 객체 수 기록(객체간 공유됨o)
	int num = 0;
	public InstCnt(){
		instNum++;
        num++;
		System.out.println("인스턴스 생성: " + instNum + ", num: " + num);
	}
}
public class HelloWorld{
	public static void main(String[] args){
		InstCnt cnt1 = new InstCnt(); // 인스턴스 생성: 1, num: 1
		InstCnt cnt2 = new InstCnt(); // 인스턴스 생성: 2, num: 1
		InstCnt cnt3 = new InstCnt(); // 인스턴스 생성: 3, num: 1
	}
}

활용예제2

자주 쓰는 함수, 변수에 대해선 static으로 선언해서 객체 생성 없이 접근할 수 있도록 하자!

System.out.println(); // static함수이기 때문에 클래스명으로써 접근할 수 있는 것이다

만약에 println()static함수가 아니었다면?

PrintStream out = new PrintStream();
out.println();   // static함수가 아니기 때문에 객체 생성해서만 접근이 가능하다

static 메서드에서 인스턴스 변수가 올 수 없는 이유

인스턴스 변수: 클래스 내부에서 static 키워드 없이 선언된 변수

class A{
	int num = 0; // 인스턴스 변수
	public static void print(){
		num++;  // *컴파일 에러 발생*
		System.out.println("print: " + num);
	}
}
public class Hello{
	public static void main(String[] args){
		A a = new A();
		a.print();
	}
}

🔔 컴파일 에러 발생이유:
print()함수가 static함수이기 때문에 클래스 로더에 의해 클래스 A가 로드될 때 Method Area에 같이 올라간다. 하지만 num은 인스턴스 변수이므로 즉, 아직 객체 생성이 되지 않았기 때문에 메모리에 올라갈 수 없어서 컴파일러 입장에서 num은 선언이 안된 변수이기 때문에 cannot resolve(선언 안된 변수접근)에러가 발생해서 컴파일에러가 발생합니다.

System.out.println()에서 out과 println의 정체는?

java.lang.System.out.println();

System은 java.lang 패키지에 묶여 있는 클래스의 이름
그러나 컴파일러가 다음문장을 자바 파일 맨 위에 선언해 주므로 java.lang은 생략할 수 있다.
import java.lang.*;

System.out.printnl()

out은 클래스 System의 이름을 통해 접근하므로

이는 System 클래스의 클래스 변수(static 변수) 이름임을 유추할 수 있다.

System.out.println();

println()은 out이 참조하는 객체의 메서드이다.

main 메서드가 public이고 static인 이유

static 인 이유

인스턴스 생성에 관계없이 맨 처음에 실행되어야 하는 함수이기 때문이다.

public인 이유

main메서드의 호출 명령은 외부로 부터 시작되는 명령이기 때문이다.

예외처리

1. try-catch

2. new throw

자바에서 예외란?

단순한 문법 오류가 아닌 실행 중간에 발생하는 정상적이지 않은 상황을 의미

자바의 기본 예외처리 매커니즘은 문제가 발생한 지점에 대한 정보 출력프로그램 종료이다.

에러는 누가 띄우는가?

int num = 2 / 0;

[실행 결과]
Exception in thread "main" java.lang.ArithmeticExcpetion: / by zero

JVM이 띄워준다!
하지만 이렇게 되면 프로그램이 죽게된다. 그렇다면 에러가 발생해도 프로그램이 죽지 않게 할려면 어떻게 해야할까? 그때 사용할 수 있는 방안(에러 처리방법)은 2가지이다.

try-catch

try{
 ...
} catch(Exception e) {
		e.printStackTrace(); // 에러문구 출력
		System.out.println(e.getMessage()); // 심플한 에러문구 출력
}

throws

예외처리를 호출한 함수 한테 맡긴다는 의미

JVM한테 (프로그래머가 처리 안하고) IOException을 던지겠다 즉, 테스트용으로 에러 처리 안 하겠다.(단지 프로그램 죽지만 말아라!)

여러 에러를 throw하고 싶다면 함수 옆에 thorws IOException, IndexOutofBoundsException 등 throws하고 싶은 에러를 작성하면 된다.

public static void main(String[] args){
		byte[] arr = {'a', 'b', 'c'};
		try{
			System.out.write(arr)
		} catch(ICException e) {
			e.printStackTrace();
		}
}

/ *
이렇게 잡아도되고
Ctle + 마우스 좌클릭으로 내부 write함수 보면 아래와 같이 되어있음
@Override
public void write(byte[] b) thorws IOException{
	write(b, 0, b.length);
}
*/

public static void main(String[] args)throws IOException{
		byte[] arr = {'a', 'b', 'c'};
		System.out.write(arr); // 에러 출력안되고 정상적으로 abc 나옴

}

예외 클래스 구분

Checked Exception

개발자가 만드시 코딩할 때 관리해줘야하는 Excpetion
(try-catch or throws로 반드시 잡아야한다. → 대부분 throws 사용o)

ex. `IOException**, **NoSuchMethodException**, **illegalityAccessException,`**

Unchecked Exception(=RuntimeException):

**InputMismatchException, ArithmeticException, ClassCastException, IndexOutofBoundException**

Error는 메모리관련된 에러가 많다

Error는 자바프로그램이 관리할 수 없어서 JVM이 해당 프로그램을 죽이게 된다.

숫자 입력 쪽에서 문자를 입력한다면?

catch (ArithmeticException e) { } 인 상태에서 

try{sc.nextIn();} 인데 문자를 입력하면 

InputMismatchException 에러가 발생한다
Scanner kb = new Scanner(System.in);

try { } 
catch (ArithmeticException arith_excep) {
    arith_excep.printStackTrace();

catch (InputMismatchException mismatch_excep)
		mismatch_excep.printStackTrace();
}

혹은

try { } 
catch (Exception e) {
    e.printStackTrace();
}

Best 코드

Scanner kb = new Scanner(System.in);

try { kb.nextInt(); } 
catch (ArithmeticException arith_excep) {
    arith_excep.printStackTrace();
}catch (InputMismatchException mismatch_excep){
		mismatch_excep.printStackTrace();

}catch (Exception e){
		e.printStackTrace();
}

이런 방식으로 코드를 짜는 것이 좋다 왜냐하면 앞서 잡아준 에러말고 다른에러가 발생할수도 있기 때문에 Excpetion으로 마지막에 다 handling 해주는 것이 안전하다 → Exceotion은 최상위에러 조상이기 때문에 다형성을 활용해서 에러처리한 예라고 볼 수 있다.

근데 만약 Exception e 를 다른 Error들보다 앞부분에서 써버린다면?

Scanner kb = new Scanner(System.in);

try { } 
catch (Exception e){
		e.printStackTrace();

}catch (ArithmeticException arith_error) {
    arith_error.printStackTrace();

}catch (InputMismatchException mismatch_error){
		mismatch_error.printStackTrace();
}

이렇게 하면 컴파일 에러가 발생(Unreachble exception block for ArithmeticException)한다

따라서 Exception을 사용할 것이라면 맨 마지막 or 단독으로 사용해야 한다

참고(Reference)

Garbage Collection in Java
[Java] Grabeage Collection의 개념및 동작 원리(1/2)

profile
부족한 부분을 인지하는 것부터가 배움의 시작이다.

0개의 댓글