안녕하세요. 추상 클래스와 인터페이스의 차이에 대해서 알아보겠습니다.

 

 


 

추상 클래스 ( Abstract Class )는,

상속을 통해 기능을 이용하고 확장시키는데에 목적이 있습니다.

 

하지만 인터페이스는,

상속을 통해 메소드의 구현을 강제시켜 동일한 동작을 약속하도록 하는데에 목적이 있습니다.

 

 

표로 추상 클래스와 인터페이스의 특징을 정리해보면 다음과 같습니다.

  추상메소드 인터페이스
상속 extends 사용 implements 사용
정의 일반 변수, 일반 메소드 정의 O 추상 메소드만 정의
public static final 변수만 정의
( 생략 시 자동으로 정의됨 )
다중 상속 다중 상속이 불가능하다. 다중 상속이 가능하다.
생성자 생성자 정의가 가능하다. 생성자를 가질 수 없음.
형태 일반 변수 + 일반 메소드 + 추상 메소드 상수 + 추상 메소드
오버라이딩 추상 메소드만 오버라이딩 하면 된다. 상속받은 클래스는 모든 메소드를 구현해야 한다.

 

 


 

인터페이스에서 메소드는 추상 메소드만 정의가능하기때문에 모든 메소드를 오버라이딩해야하고, 

추상클래스는 추상 메소드만 오버라이딩하면 되고 일반 변수나 일반 메소드 정의가 가능하다는 차이점이 가장 큰 것 같습니다.

 

안녕하세요. 오늘은 접근 지시자 = 접근 제한자에 대해서 알아보겠습니다.

 


 

Java에서는 접근 제한자를 통해 액세스를 제어할 수 있습니다.

종류로는 public, protected, default, private 가 있습니다.

 

- private

private는 해당 클래스에서만 접근을 허용합니다.

 

- default

같은 패키지에서만 접근을 허용합니다. (접근 제한자를 생략한 경우)

 

- protected

같은 패키지에서 접근을 허용하고, 다른 패키지는 해당 클래스를 상속을 받아야 접근이 가능합니다.

 

- public

모두 접근을 허용합니다.

 

Class에는 default, public 접근 제한자를 사용 가능하고

변수 및 메소드에는 위 4가지 모두 사용 가능합니다.

 

 


Java의 특징인 캡슐화에 지분이 있는 접근 제한자에 대해 알아보았습니다.

 

 

 

안녕하세요.

오늘은 자주 사용되는 String과 StringBuilder, StringBuffer에 대해서 포스팅해보겠습니다.

 

 


 

# 공간적 차이

- String

String은 값 변경 시, Heap영역에 공간이 새로 생성됩니다. 추후에 GC에 의해 제거됩니다.

 

- StringBuilder, StringBuffer

이 둘은 값 변경 시, Stack공간에 값을 저장해 값만 바꿔씁니다.

 

-> 따라서 값이 자주 변경된다면 String보다는 StringBuilder, StringBuffer 사용을 권장합니다.

 

 

 

# 시간적 차이

 

글보단 시간측정을 해보겠습니다.

	public static void main(String[] args) throws Exception{
		
        // 1. StringBuilder 시간 측정
		long time1 = System.currentTimeMillis();
		StringBuilder builder = new StringBuilder();
		for(int i=0;i<100000000;i++) {
			builder.append("a");
		}
		long time2= System.currentTimeMillis();
		System.out.println("StringBuilder ::: " + (time2 - time1));
		
        // 2. StringBuffer 시간 측정
		long time3 = System.currentTimeMillis();
		StringBuffer buffer = new StringBuffer();
		for(int i=0;i<100000000;i++) {
			buffer.append("a");
		}
		long time4= System.currentTimeMillis();
		System.out.println("StringBuffer ::: " + (time4 - time3));
		
        // 3. String 시간 측정
		long time5 = System.currentTimeMillis();
		String str = "";
		for(int i=0;i<500000;i++) {
			str += "a";
		}
		long time6= System.currentTimeMillis();
		System.out.println("String ::: " + (time6 - time5));
		
	}

StringBuilder와 StringBuffer는 각각 1억건의 연산을 했을 때,

String은 Heap사이즈가 초과해서? 오래걸려서? 그런지 1억건으로 하니 측정이 안되서 50만건 연산했을 때

각각의 속도를 측정해보았습니다.

 

 

- 결과

결과가 보이시나요? 비교적 적은 50만건만 연산한 String의 속도가 현저히 느린 것을 확인할 수 있었습니다.

1억건씩 연산한 StringBuilder와 StringBuffer는 StringBuilder가 현저히 빠른 것을 볼 수 있었습니다.

 

"? 그러면 StringBuffer는 언제쓰는거지?" 라는 의구심이 들어 찾아보았습니다.

 

StringBuffer는 StringBuilder와 다르게 동기화를 지원하여, 멀티 쓰레드 환경에서 안정성을 가지고 있습니다.

 

 

- 결론

문자열 단순 조회 용도 = String

연산이 (추가,삭제 등 ) 자주 일어날 때에, 단일 쓰레드 환경 -> StringBuilder

연산이 (추가,삭제 등 ) 자주 일어날 때에, 멀티 쓰레드 환경 -> StringBuffer

 

 


자주 사용되는 문자열을 저장하는 객체들에 대해서 알아보았습니다.

보통은 단일 쓰레드환경에서 자주 사용하니 StringBuilder를 잘 기억해놓아야겠네요!

 

감사합니다.

'Java' 카테고리의 다른 글

[Java] 추상 클래스 vs 인터페이스  (0) 2021.09.03
[Java] 접근 제한자란?  (0) 2021.09.02
[Java] Garbage Collector  (0) 2021.08.25
[Java] JVM이란? 정의 및 동작 방식  (0) 2021.08.22
[Java] 특징 1. 객체지향 프로그래밍  (0) 2021.08.21

안녕하세요.

오늘은 Garbage Collection(Collector)에 대해서 포스팅해보려고 합니다.

 

 


 

JVM의 Heap Area에 남은 더 이상 사용하지 않는 인스턴스를 Garbage라고 하며,

이 Garbage를 효과적으로 처리하는 작업을 Garbage Collection. 이를 수행하는 프로그램을 Garbage Collector 라고 합니다.

 

예를 들면 아래와 같은 코드가 있을 때.. 

// 지역 변수일 때
String text1 = "hello";

text1 = "Java";

이전 포스팅에서 알아본 바에 따르면, 위 코드는

 

 

text1은 Stack 영역에 저장이 되고 "hello" 문자열은 Heap 영역에 저장이 됩니다.

text1은 Heap영역의 주소 값을 가지고 있으며 그 주소 값은 hello를 가르키게 됩니다.

이후에 text1이 가르키는 주소 값을 "Java"로 변경했습니다. 

 

그러면 Heap 영역에 저장된 "hello" 값은 어떻게 될까요??

이게 바로 Garbage가 됩니다.

지금은 하나지만, 프로젝트가 규모가 커질수록 쌓이는 Garbage들이 많아질텐데, 이를 관리 안해주면 메모리를 많이 차지하고 있겠죠?

이를 자동으로 관리해주는 프로그램을 Garbage Collector라고 합니다.

 

Garbage Collector는 두 가지의 가설을 전제로 만들어졌습니다.

1. 대부분의 객체는 금방 unreachable 상태가 된다. < 금방 garbage 상태가 된다. >

2. Old 객체가 Young 객체를 참조하는 일은 아주 적게 일어난다. 

 

쉽게 설명하자면 "대부분의 객체가 금방 아무도 참조하지 않는 상태가 되며", "생성된 지 오래된 객체가 최근에 생성된 객체를 참조하는 일은 아주 적게 일어납니다."

라는 것을 전제로 설계되어 만들어 졌다는 뜻입니다.

 

Garbage Collection의 동작 방식을 알아보기 전에 Mark and Sweep, Stop the World 작업에 대해서 알아보겠습니다.

 

- Mark: 사용되는 메모리와 사용되지 않는 메모리를 식별하는 작업. ( Reachable 상태와 Unreachable 상태 식별 )

- Sweep: Mark 단계에서 식별된 사용되지 않는 메모리를 제거하는 작업.

- Stop the World: GC 실행을 위해 GC 쓰레드를 제외한 모든 쓰레드의 작업을 멈추는 것을 말합니다. Application이 잠깐 중지되며, GC 알고리즘의 종류에 따라 STW 시간이 다릅니다.

- Compact: GC 알고리즘의 종류에 따라서 존재하는 작업으로, Sweep 후 분산되어 있는 객체들을 Heap의 한 곳(시작 주소)로 모아 메모리의 분산화를 막아줍니다.

 

 

Java 8 버전을 기준으로, Heap영역은 Young Generation과 Old Generation. 이 두 영역으로 나누어집니다.

 

- Young Generation: 새롭게 생성된 객체가 할당되는 영역으로, 이 영역에 대한 GC를 Minor GC라고 합니다.

- Old Generation: Young 영역에서 Reachable 상태를 유지해 살아남은 객체가 복사되는 영역으로, 이 영역에 대한 GC를 Major GC라고 합니다. 

 

# Garbage Collector 동작 과정

1. 새로운 객체는 Eden 영역에 할당됩니다.

 

2. Eden 영역이 꽉차면 Minor GC가 발생하여 Mark and Sweep 과정이 일어납니다.

 

3. Unreachable로 식별된 객체들은 삭제되며 Reachable 상태로 식별된(마킹된) 객체들은 survivor 영역으로 이동하며  Age값이 증가합니다.

< 규칙 :: survivor0 영역에 객체가 있으면, survivor1 영역은 무조건 비워져있어야 합니다. 반대도 마찬가지. >

- 다음 Minor GC가 발생하면 반대편 survivor 영역으로 이동합니다.

 

4. 2~3의 과정이 반복되어, 객체의 AGE값이 특정 값. 임계치에 도달하게 되면 Old Generation으로 이동하게 됩니다. 이를 Promotion이라고 합니다.

 

5. Old Generation이 꽉 차면 Major GC가 발생합니다.

 

 

GC의 종류(알고리즘의 종류)는 다음과 같습니다.

 

1. Serial GC

- GC를 처리하는 쓰레드가 1개라서 다른 GC에 비해 STW 시간이 깁니다.

- Mark and Sweep 후 Compact 과정이 포함됩니다. 

 

2. Parallel GC

- Java 8의 Default GC로, Young 영역의 GC를 멀티 쓰레드로 수행합니다.

- Serial GC에 비해 STW 시간이 짧습니다.

 

3. Parallel Old GC

Parallel GC를 개선한 것으로, Old 영역에서도 멀티 쓰레드로 GC를 수행합니다.

- Mark-Summary-Compact 알고리즘을 수행합니다.

< Sweep: 단일 쓰레드, Summary: 멀티 쓰레드 >

 

4. Concurrent Mark Sweep GC

- STW 시간을 줄이기 위해 고안된 방법으로, 다음 4단계를 거칩니다.

1) Initial Mark: GC Root에서 참조하는 객체들만 식별합니다.

2) Conccurent Mark: 이전 단계에서 식별된 객체들이 참조하는 모든 객체를 추적합니다.

3) Remark: 이전 단계에서 식별한 객체들을 다시 추적하여, 추가되거나 끊긴 객체를 확정합니다.

4) Concurrent Sweep: 최종적으로 Unreachable 객체를 삭제합니다.

- 과정이 많기 때문에 CPU의 부하가 커진다는 단점이 있습니다.

 

5. G1 GC (Garbage First)

- Concurrent를 개선한 것으로, 이전 GC들은 큰 용량의 메모리 적합하지 않습니다. ( Root Set 부터 탐색하기때문에 용량이 크면 탐색 시간이 길어짐 )

- 큰 Heap 메모리에서 짧은 GC 시간을 보장하는 데에 목적이 있습니다.

- Heap 메모리를 물리적인 영역(Young-Old Generation)으로 나눈게 아니라, Region이라는 일정한 크기의 영역으로 나눕니다.

- Region은 최대 2048개로 나뉠 수 있으며, 각각 1~32MB의 크기를 가집니다.

- 핵심은 Heap을 동일한 크기의 Region으로 나누고, Garbage가 많은 Region에 대해 우선적으로 GC를 수행하는 것 입니다.

 

 


 

Garbage Collector가 무엇인지, 어떻게 동작하는지, 종류로는 어떤 것이 있는 지에 대해 알아봤습니다.

 

 

참고 사이트

https://mangkyu.tistory.com/119

https://www.youtube.com/watch?v=Fe3TVCEJhzo

 

안녕하세요~ Java Virtual Machine에 대해 포스팅해보려고 합니다. 

 

Java는 운영체제에 독립적이라는 특징을 가지고 있는데요,

이는 운영체제와 상관 없이 어디서 개발하더라도 어디서든 실행할 수 있다는 것(WORA)을 말합니다.

이는 JVM 덕분입니다!

 

 

JVM = Java Virtual Machine

JVM 은 자바 바이트 코드(Class 파일)를 OS에 특화된 코드로 변환하여 실행합니다. 

-> 특정 OS에 특화된 코드로 변경하기 때문에 JVM은 플랫폼에 종속적이지만, 이 JVM 덕분에 Java 자체는 플랫폼에 독립적이게 됩니다.

 

 

JVM은 크게 4가지로 구성됩니다.

1. Class Loader

2. Execution Engine

3. Runtime Data Area (Memory)

4. Native

 

 

1. Class Loader

.Java 파일을 자바컴파일러가 컴파일 하면, .class 파일이 생성됩니다. ( 자바 바이트 코드 )

이렇게 생성된 클래스 파일들을 메모리(Runtime Data Area)에 적재시키는 역할을 합니다.

 

2. Execution Engine

Class Loader에 의해 메모리에 적재된 .class 파일들을 기계어로 변경해 명령어 단위로 실행하는 역할을 합니다. 

 

3. Runtime Data Area

실행된 인스턴스(데이터)들이 적재되는 JVM의 Memory 영역입니다.

 

Runtime Data Area는 다음과 같은 영역으로 구분되어 있습니다.

Area Data
Method Area Field의 정보(클래스 전역 변수의 이름, 데이터 타입, 접근 제어자 등)
Method의 정보(이름, Return Type, 접근 제어자, 파라미터 등)
Type 정보( 인터페이스인지, 클래스인지)
static 변수 등이 저장되는 영역입니다.
Heap Area 객체, 배열이 생성되는 영역입니다.
Stack Area 지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값이 생성되는 영역입니다.

< Animal an = new Animal(); 이란 소스 작성을 하면,
an은 Stack 영역에 생성되고 new로 생성된 Animal 인스턴스는 Heap 영역에 생성됩니다. an은 Heap 영역의 주소 값을 가지고 있습니다.

한줄정리: Stack 영역에 생성된 an이 Heap 영역에 생성된 인스턴스를 참조한다.>
PC Register Thread가 생성될 때 마다 생성되는 영역으로,
현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역입니다.
Native Method Stack 자바 외의 언어로 작성된 Native 코드를 위한 메모리 영역입니다.

 

Heap, Method 영역은 모든 쓰레드가 공유하는 영역입니다. 

 

 

 

출처: https://webdevtechblog.com/jvm-java-virtual-machine-architecture-94b914e93d86

이와 같은 역할을 하는 JVM을 포함하여 Library와 함께 Java RunTime Environment를 구성합니다.

따라서 JRE 만 설치하면 모든 플랫폼에서 Java 어플리케이션을 실행할 수 있게 됩니다.

 

 

JVM이 동작하는 전체적인 흐름을 요약하자면 다음과 같습니다.

 

1. Java Compiler가 Java 파일을 Class 파일로 변환합니다.

2. Class Loader가 Class 파일을 Runtime Data Area 에 적재시킵니다.

3. Execution Engine이 적재된 Class들을 기계어로 변환하여 명령어 단위로 실행(인터프리터)합니다.

(4. Garbage Collector 가 Heap 영역에 적재된 객체들 중 참조되지 않고 있는 객체를 제거해 메모리를 관리합니다.)

 

 

 


 

 

JVM의 동작 방식에 대해 알아봤습니다! 

추후에 Heap 영역과 관련된 Garbage Collection 에 대해 포스팅하겠습니다~

 

감사합니다.

 

 

 

참조:

https://jeong-pro.tistory.com/148

https://webdevtechblog.com/jvm-java-virtual-machine-architecture-94b914e93d86

 

안녕하세요. 

Java의 특징들에 대해 다시 공부해볼 겸 포스팅을 한 번 해보려고 합니다.

 

Java는 대표적인 객체 지향 프로그래밍 언어 중 하나로, 특징은 다음과 같습니다.

1. 객체 지향 프로그래밍 (OOP) 

2. 메모리를 자동으로 관리함

3. 운영 체제에 독립적

4. 멀티 쓰레드 지원

 

그중에서 객체 지향 프로그래밍에 대해 포스팅해보겠습니다.

 

 

 


 

 

객체 지향 프로그래밍이란, (= OOP = Object Oriented Programming )

프로그래밍이 필요한 데이터를 하나의 '객체'로 보고 상태(속성)와 행위(Method)를 가진 객체로 구현하는 프로그래밍 방식을 말합니다.

 

예를 들어 "동물"을 객체 지향 프로그래밍의 관점으로 본다면,

일반적으로 동물들은 공통적으로 눈, 코, 입을 가지고 있고 ( 상태 ) 먹기, 잠자기, 숨쉬기와 같은 행위 (Method)를 합니다.

 

이와 같이 추상화 시킨 '동물' 객체를 Class라고 합니다.

 

 

 

객체 지향 프로그래밍의 대표적 특징 4가지는 다음과 같습니다.

 

1) 상속

다른 클래스의 속성과 메소드를 물려받는 것을 말합니다.

 

예를 들어 '동물' 클래스의 특징을 모두 가지고 있는 '고양이'는 '동물' 클래스를 상속받을 수 있겠죠?

 

 

2) 다형성

객체는 여러 형태로 재구성될 수 있다 는 것을 말합니다.

 

예를 들어 '동물' 은 고양이로도 표현될 수 있고, 강아지로도 표현될 수 있겠죠?

 

3) 추상화

객체의 공통된 속성과 기능을 묶어 정의하는 것을 말합니다.

 

'동물' 은 고양이, 강아지에게도 공통된 속성을 가지고 있는 것을 확인할 수 있습니다.

 

4) 캡슐화

객체의 속성과 메소드를 하나로 묶고, 실제 구현 내용을 외부로부터 감추는 것을 말합니다.

 

 

객체 지향 프로그래밍의 장점은 다음과 같습니다.

1. 상속을 통해 코드의 재사용성이 좋습니다.

2. 클래스 단위로 모듈화가 가능하여 대형 프로젝트에 적합합니다.

 

단점은 다음과 같습니다.

1. 처리속도가 상대적으로 느립니다.

2. 객체가 많으면 용량이 커집니다.

 

 


 

이상으로 객체 지향 프로그래밍에 대해 포스팅해보았습니다.

 

+ Recent posts