1. Java에서 비교연산자

프로그래밍 언어에서 자주 사용되는 '=='과 '!='이라는 두 연산자는 두 변수가 동일한 값을 갖고있는지 파악하는 용도로 많이 사용됩니다.

 

특히 조건문에서 많이 사용되죠.

 

가볍게 사용하고 있지만, Java에서 이 연산자들은 단순히 동일한 값을 확인하는 용도로 사용되지 않습니다.

 

왜냐하면, 이 연산자의 양옆에 오는 값이 동일한 것인지를 확인하는 것이 아닌, 양옆에 오는 두 객체가 동일한 참조를 하는지 확인하는 용도로 사용되기 때문입니다.

 

 

앞서 JVM가 메모리 영역을 어떻게 관리하는지 생각하며 진행해보겠습니다.

 

JVM Stack 영역에 저장되어있는 '참조 변수'는 아래와 같은 구조로 저장되어있습니다.

 

var1 Heap 3번
var2 Heap 8번
var3 Heap 11번

 

각각의 '참조 변수'는 힙 영역의 특정 위치를 가리키고있고, 이를통해 힙영역에 저장되어있는 실제 데이터에 접근하게됩니다.

 

만약 Heap영역 3번과 8번이 동일한 값을 갖고있다면, var1 == var2라고 했을 때 어떤 값을 반환받을까요?

 

정답은 'False'입니다.

 

힙 영역에는 둘 다 같은 값은 갖고있다해도 참조하는 Heap영역의 주소가 다르기 때문에 False라는 값을 반환하게됩니다.

 

 

 

2. 객체의 생성

위와같이 Java라는 녀석에서 '참조변수'는 참조하는 힙영역이 어디냐에 따라 True나 False를 반환하지만, 실제 코드를 사용할 때에는 가끔 이러한 것들이 이해가 안되는 경우를 볼 수 있습니다.

 

 

만약 아래와 같은 코드를 수행했다고 생각해봅시다.

 

String user1 = "YoungQ";

 

위의 코드를 수행하면 Heap영역 어딘가에 "YoungQ"라는 데이터를 갖고있는 객체가 생성될 것입니다. 여기서는 그곳을 Heap 1번이라고 가정하겠습니다.

 

Heap1 : "YoungQ"

 

위와같이 Heap영역에 1번에 "YoungQ"라는 값이 들어간다면, user1은 Heap1을 참조하게 될 것입니다. 그럼 전체적으로 보면 아래와 같은 형태가 됩니다

 

Stack 영역 Heap 영역
user1 : Heap1 Heap1 : "YoungQ"

 

 

그럼 여기서 아래와 같은 코드를 수행하면 어떻게 될까요?

 

String user2 = "YoungQ";

 

user1과 마찬가지로 새로운 Heap2 영역에 "YoungQ"라는 데이터가 들어갈 것이라고 생각되지만, 그렇게되면 동일한 데이터를 위해 여러 메모리를 할당하는 형태가되기 때문에, 메모리 낭비가 문제가 발생하여 Java에서는 다르게 이를 처리합니다.

 

방식은 간단합니다. 동일한 데이터가 이미 Heap영역에 존재한다면, 그곳을 참조하도록만 만들어주면 되는것이죠.

 

메모리상에는 아래와 같이 들어갑니다.

 

Stack 영역 Heap 영역

user1 : Heap1

user2 : Heap1

Heap1 : "YoungQ"

 

일반적으로 이러한 동시참조의 문제는 user1의 데이터를 변경했을 때, user2의 데이터도 변경되는 문제가 발생한다는 것입니다.

 

그렇게되면 정말 큰 문제가 되죠.

 

하지만, 걱정하지마세요. 하나의 데이터를 변경하게되면, 변경된 데이터로 새로운 객체를 만들어 참조할 힙영역의 주소를 알아서 변경해주니까요.

 

더보기

참고로 원하는 경우 새로운 객체를 만드는 방법도 존재합니다.

 

String user1 = "YoungQ";

String user2 = new String("YoungQ");

 

이와같이 코드를 작성하면 힙 영역에 두 개의 "YoungQ"라는 데이터를 갖은 객체가 생성됩니다.

 

실행결과

 

 

3. NULL 참조

값이 존재하지 않는 경우를 흔히 null로 표시하는 경우가 많이 있습니다.

 

참조변수도 이러한 null값을 갖을 수 있습니다.

 

String user3 = null;

 

위의 코드에서 user3라는 변수는 존재하지만, user3는 어떠한 영역도 참조하지 않는 변수를 의미합니다.

 

이러한 null은 Java 뿐만아니라 다양한 곳에서 사용됩니다. 하지만, 유독 Java에서 null이라는 녀석 문제가 되는데 그 이유는 Java가 대표적인 객체지향 언어이기 때문이죠.

 

많은 것들이 객체 단위로 이뤄지기 때문에 툭하면 NPE(Null Pointer Exception)이라는 애러를 발생시킵니다.

 

Null 값을 참조하려하면 발생하는 녀석이죠.

 

 

실행결과

 

위와같이 말이죠.

1. JVM의 메모리 관리

Java 프로그램을 실행하게되면 운영체제로부터 JVM(Java Vitrual Machine)은 메모리를 할당받고 이를 몇가지 영역으로 세분화하여 관리하게됩니다.

 

JVM은 메모리를 메소드 영역(Method Area), 힙 영역(Heap Area), 스레드 단위(Thread)로 구분하여 관리하게됩니다.

 

각가의 영역에서 어떤 데이터들을 관리하는지 알아보겠습니다.

 

 

2. 메소드 영역(Method Area)

메소드 영역에서는 '.class 파일'들을 읽어들여 각각의 클래스별로 런타임 상수풀, 필드 데이터, 메소드 데이터, 메소드 코드, 생성자 코드 등을 저장하게됩니다.

 

일반적으로 static으로 선언된 값들 역시 이 과정에서 메소드 영역에 저장되게됩니다.

 

이곳에 생성된 데이터는 JVM이 실행되는 순간에 자동으로 생성됩니다. 프로그래밍 과정에서 아직 수행되지 않은 static 영역의 데이터에 접근할 수 있는 이유도 static으로 선언된 값이 JVM이 실행되는 순간에 메모리에 올라가기 때문입니다.

 

여기에 저장된 값들은 모든 쓰레드가 공유하는 값이라는 것을 유의해야합니다.

 

 

 

3. 힙 영역(Heap Area)

힙 영역은 객체(Object)와 배열(Array)이 사용하는 공간이라고 볼 수 있습니다.

 

객체와 배열의 공통점은 이 두가지를 '참조'를 통해 호출한다는 것에 있습니다. C에서 주소값을 통해 배열에 접근하는 방식과 유사하다고 볼 수 있습니다.

 

Java에서 빠질 수 없는 녀석인 gc(Garbage Collector)가 바로 이 힙 영역에 존재하는 객체와 배열들을 정리하는 역할을 수행합니다.

 

어떠한 곳에서도 참조하는 변수나 필드가 없다면 이것을 쓰레기라고 판단하고 gc가 힙 영역에서 이 객체들을 제거하는 역할을 수행하게됩니다.

 

gc의 존재 덕분에 프로그래머가 객체를 제거하기 위한 코드를 작성할 필요가 없습니다. 다만, gc의 경우 항상 실행되고 있는 것이 아니라 필요에 따라 JVM에의해 실행되기 때문에 필요로 하지 않는 객체가 당분간 힙 영역에 존재하는 경우가 있을 수 있습니다.

 

만약 참조하지 않는 객체를 즉시 gc에 의해 정리하고 싶다면, System.gc();를 통해 gc를 실행시킬 수 있습니다.

 

 

 

4. 스레드(Therad)

JVM은 한 프로그램의 작업단위를 의미하는 스레드(쓰레드) 별로 데이터를 나눠 관리합니다.

 

이는 하나의 스레드에서 관리하는 데이터에 다른 스레드가 접근하지 못하는 일이 없도록 데이터의 관리단위를 나눠주기 위함이라고 생각합니다.

 

하나의 스레드 영역에는 JVM 스택(JVM Stack)이라는 영역이 존재합니다.

 

일반적인 데이터 관리형태와 마찬가지로 Stack 구조를 이용하여 스레드에서 사용하는 변수(지역변수 + 참조타입변수)들을 관리하게됩니다.

 

 

1. Project 시작하기

이클립스를 시작하고, workspace를 선택해주시면 welcome 화면이 표시되고 이걸 꺼주시면 아래와 같은 화면을 볼 수 있습니다.

 

 

먼저 좌측에 Project Explorer라는 부분을 볼 수 있는데요.

 

기본적으로 하나의 프로그램은 Project 단위로 관리된다고 생각하시면 좋습니다. 하나의 Project 영역을 생성하고, 여기에 기본적인 코드부터 GUI를 위한 xml, 이미지 파일등 올려두고 관리합니다.

 

그럼 먼저 Project를 생성하겠습니다.

 



 

 

 

 

우측 Project Explorer 부분을 보게되면 다양한 용도를 위한 Project들이 존재하는 것을 볼 수 있습니다.

 

저희는 [Java Project]를 사용할 예정이기 때문에 [Create a project...] 라는 녀석을 눌러주세요.

 

그럼 아래와같이 New Project 라는 창이 등장합니다.

 

 

 

 

 

 

 

 

 

 

 

 

여기서 [Java Project]를 클릭해주세요. 그럼 아래와 같은 창이 등장합니다.

 

 

 

Project name에 원하는 값을 입력해보세요. 그럼 하단에 [Next]와 [Finish]가 활성화 됩니다.

 

[Next]를 눌러 다음으로 넘어가주시면, 몇가지 추가 설정이 있는데 여기서 모듈생성에 대한 부분을 아래와 같이 해제하신 후 [Finish]를 눌러주세요.

 

 

그럼 아래와 같은 창이 보입니다.

 

 

이렇게 Project를 생성했습니다. 다음으로 package를 만들겠습니다.

 

 

 

2. Package 생성

 

여기서 잘보시면 [Project Explorer] 라고 되어있던 부분이 [Package Explorer]라고 변경된 것을 볼 수 있습니다.

 

펼쳐보면 아래와 같은 상태가 됩니다.

 

 

 

Package는 여러 코드들을 용도에 따라 구분해 정리하기 위한 폴더단위라고 생각하시면 좋을꺼같습니다.

 

Package를 'src'이하에 생성해 보겠는데요. Package 이름은 '소문자'를 사용하는게 약속입니다.

 

1) src 우클릭 -> New -> Package 클릭

2) package 이름 입력(소문자쓰기) -> 생성

src 이하에 패키지 생성완료

 

 

 

 

3. Java Class 생성

Java는 Class 기반 언어라고 불립니다. 그렇기에 모든 코드는 Class라는 단위에서 작성되고 실행됩니다.

 

그렇기 때문에 흔히 C언어에서 'Main'이라고 부르는 부분 역시도 Java에서는 Class로 정의됩니다.

 

Class 생성을 해보겠습니다.

Class의 이름은 '대문자'로 사용하는게 약속입니다~!

 

1) 패키지 우클릭 -> New -> Class

 

 

2) Class 이름 입력(클래스는 대문자) -> [public static void main(String[] args] 선택 -> Finish

public static void main(String[] args) create 는 해당 클래스에 main 영역을 생성한다는 의미로 생각하시면 됩니다.

 

 

3) 패키지 아래 HelloWorld.java 클래스 생성 완료

 

 

4. Hello World 출력하기

 Java에서 print는 왜 이렇게 길까... 라고 종종생각합니다.

 

아래 코드를 봐주세요.

 

실행화면

겨우 Hello World를 출력하는데도 앞에 System.out 이라는 녀석들이 붙습니다.

 

printf, print 등에 익숙했던 입장에서는 불편하게 보일 수 있습니다.

 

하지만, 나중에보면 이게 꽤 직관적이여서, 구문을 이해하는데 유용할 때도 있습니다.

 

 

 

 

Java라는 녀석도 코딩을 한 후 '컴파일'이라는 과정을 수행해야 실행할 수 있는 상태가됩니다.

 

이클립스에서는 여기에 대해 편리하는 기능을 제공하는데요.

 

바로 사용자가 코드를 [저장]하면 자동으로 컴파일을 수행하게됩니다.

 

때문에 코드를 작성하고 [저장] -> [실행]을 수행하면 별도로 컴파일을 수행하는 부분없이 코드가 실행됩니다.

 

만약 수정된 코드를 저장하지 않고 실행하면 아래와 같은 창이 뜨게 됩니다.

 

 

[ Save == 컴파일 ] 이라는 관점에서 보면, 이 창은

 

"컴파일을 수행하고 실행할까요?"

 

라는 의미를 갖습니다.

 

 

단, 혹시라도 실수로 Project에 Build Automatically를 해제한 상태라면, 위와같은 자동 컴파일이 수행되지 않습니다.

 

 

 

 

이클립스를 통해 프로그래밍의 시작인 "Hello World"를 출력해보았습니다.

 

이제 시작입니다~!

 

 

 

'프로그래밍 > Java 기초' 카테고리의 다른 글

[Java 기초] 2. Project 시작하기  (0) 2019.12.25
[Java 기초] 1. Java 설치  (0) 2019.12.24

+ Recent posts