본문 바로가기

카테고리 없음

한번에! 자바 이해하기 : 클래스, 객체, 인스턴스 차이에 초점을 맞춰서

728x90

Java 글은 Java Virtual Machine SE 8  문서와 Java Language SE 8 Specification 문서와 wikipedia에서 나온 내용을 중심으로 이해한 것을 포스팅 할 예정입니다. 그 이유는 첫째 Spec 문서가 가장 기본이 되는 설명이기 때문이고, 둘째, 하나의 기준이 생기므로 문제가 발생했을 때 그 원인을 찾기 쉽습니다. 아마도 문제의 대부분의 원인은 제가 오역을 하거나 이해를 잘못했기 때문이겠죠?^^;;



자바란?


 자바란 프로그래밍 언어입니다.  특징은 크게 3가지가 있는데 concurrent, class-based, object-oriented가 그것들 입니다. 


 첫번째, Concurrent 란 해석하면 "경쟁하는 공존하는"으로 wiki 에선 concurrent computing으로 검색됩니다. 이와 반대된는 말로 sequentially가 있고 이때 sequentially는 다음 것이 시작되기 전에 하나가 완료되는 방식을 말하고 따라서 이와 반대되는 concurrent는 겹치는 시간에 여러 계산이 실행되는 것을 말합니다. 따라서 자연스레 thread 제어와 연결이 될것으로 보이네요. 그리고 이것은 현대 프로그래밍의 패더라임 중 하나입니다. (JLS chapter 17  Threads and Locks 참고하시면 될 거 같습니다.)

( 저에게는 concurrent라는 속성이 non-blocking i/o 라는 개념 그리고 parallel programming이라는 개념과 뒤섞이며 혼란스럽네요...  지금 당장 드는 생각은 concurrent는 non-blocking i/o와 함께 다음에 찾아보도록 하죠.)


 두번째, class-based 입니다. 이는 곧 class 기반을 말하며 기본적으로 결과물(object)가 class 기반에서 만들어지는 것을 말할 뿐만 아니라 상속이 object의 class를 정의함으로서 달성되는 OOP(Object-Oriented Programming:객체지향프로그래밍)의 스타일을 말합니다. 이와는 다른 prototype-based programming이 있습니다. 이것도 OOP의 스타일 중 하나입니다. 이는 상속이 프로토타입의 역할로서 존재하는 object를 복제하는 과정을 거쳐 이뤄지는 것을 말합니다. 여기서 상속이란 행위의 재사용입니다. prototype-based programming과 같은 말로 instance-based programming이 있습니다. prototype-base programming에 대해 wiki에서는 다음과 같이 예를 들어 줍니다. 과일이라는 object가 있을 때 바나나는 과일 object를 복사하여 바나나에 특화된 일반적 속성을 포함시키며 확장됩니다. 그 다음 다른 바나나 object는 그 일반적인 바나나 object로 부터 복사가 되는 거죠.  class, object, prototype ... 뭐이리 다양한지. 하지만 그냥 넘어갑니다. (자세히 알기 위해선 더 찾아봐야겠죠?) 자바스크립트가 이에 해당하네요.

 그렇다면 class-based에서의 상속은 어떻게 될까요? 상속 받기위해선 상위 class가 있어야 하고 그 상위 class를 상속 받으면 상위 class의 state 와 behavior를 그대로 물려 받습니다. class-based와 prototype-based각각에서의 상속이 무슨 차이인지 모르겠어서 이에 대해 찾아봤습니다.


http://stackoverflow.com/questions/816071/prototype-based-vs-class-based-inheritance

http://stackoverflow.com/questions/2800964/benefits-of-prototypal-inheritance-over-classical/


결국엔 class로 부터 상속을 받느냐 prototype으로부터 상속을 받느냐 하는 거죠.  Java Script가 prototype-based네요.

검색을 해보니 아래와 같습니다.




그래서 jscript에서는 function 이 그렇게나 많았던거네요. (node.js 할 때도 이해가 안됐다는...)

(요정도로만 마무리...)



 세번째, object-oriented 까지 왔네요. object란 state와 behavior를 가지고 있는데 이것들은 다시 attributes 와 methods, 그리고  fields와 procedures와 연관이 되며 이 것들을 담는 구조를 말합니다. 따라서 object-oriented란 객체 지향이란 말은 결국 데이터를 담을 때 흡사 object와 같이 담겠다는 거고 OOP는 그것을 지향하는 현대적인 프로그래밍 패러다임입니다.(한편 이것은 structured programming에 속한다고 하네요. 아~ 많다.) 꼭 그렇게 데이터를 담아야 한다는 것도 아니고 그저 그런 스타일을 추구하는 것이죠. C도 하나의 스타일이 있겠네요? 스타일에 대한 말이 나온 김에 Java와 C가 데이터 표현에 있어서 비슷한 이유를 찾아봤습니다. 자바에는 두가지 데이터 타입이 있습니다.  Primitive Type과 Reference Type이죠.


There are two kinds of types in the Java programming language: primitive types

(§4.2) and reference types (§4.3).                        --JLS   4.1 The Kinds of Types and Values



 Primitive Type 은 흔히 C에서 쓰는 data 타입들을 말합니다. int char 등등 이요...  Java를 이렇게 설계 했으니 그래서 Java에서도 일부 C와 같은 데이터 표현이 가능한거죠. 그리고 데이터 타입을 설정하는 타임도 중요한데요. Javascript에서는 목적(연산)에 상관없이 모든 변수를 var로 처리했던거 같은데 가물가물하네요. 이를 untyped language라고 한다네요. Java나 C는 statically typed programming language고요.)


그리고 자바의 Reference type은 Object와 연관이 있어 보입니다.

 There are four kinds of reference types: class types (§8.1), interface types (§9.1),There are four kinds of reference types: class types (§8.1), interface types (§9.1),                 -- JLS 4.3 Reference Types and Values


 Reference type 에는 Class 이 종류에는 모두 identifier가 존재합니다. 흔히 우리가 Object라고 하는 array, class, interface 것들은 identifier가 존재합니다.( JLS Chapter 4)

(근데 여기서 TypeVariable은 뭔지 잘 모르겠네요.)

(interface가 object가 아니라는 얘기가 있는 거 같지만 그냥 씁니다.)




[중간 정리]

 공부 할게 많군요. 언어는 결국 데이터를 어떤 형태로, 어떻게 저장하고, 언제 저장할 것이고, 어디에 저장할 것인가, 어떤 형태로 불러올 것인가를 결정하고 그 스타일을 정하면 그것이 based가 된 언어가 되는 걸로 이해했습니다. 그래서 자바는 class 기반의 언어이며 object의 형태로 데이터를 저장하는 것을 지향하며 이런 데이터를 순서에 상관없이 실행 할 수 있는 그런 언어란 말이죠.




이제  class, object 그리고 instance가 뭔지 궁금해지네요.

이보다 먼저 이해할 게 있다고 생각합니다. 바로 코드가 동작하는 원리죠. (JVM참고)

이래나 저래나 프로그래밍을 해서 프로그램을 만들려면 우선 언어를 알아야 겠지만 프로그램이 돌아가는 환경, 원리를 알아야된다고 생각합니다.


1.언어로 짠 code 가 있고 이 것은 하드디스크(보조기억장치)에 있겠죠.

-> 2.실행가능하고 램에 로딩 가능한 형태로 변환 그 결과도 어떤 code 겠고 하드디스크(보조기억장치)에 있겠죠.

-> 3. 그 다음 램으로 올립니다. (주기억장치)


이것이 말하는 대상은 언어에 따라 다르겠지만 Java에서는

1. .java file

2. .class file

3. .class에 있는 어떤 요소들과 JVM 상호 작용에서 나온 산물들


이걸 인지하고 class와 object를 이해해 봅시다.


클래스란(class)?

 하나의 확장된 template 입니다. 이를 통해 object가 생성됩니다. 그러면 이 class가 만들어진 object는 뭘까요?


객체란(object)?

(wiki 참고) 식별자에 의해 참조된 값을 가지고 있는 메모리의 지점을 말합니다.(무슨 메모리일까요?) object는 변수가 될 수도 있고, 데이터 구조 또는 함수가 될 수 있습니다. class based OOP에서 object란 그 object가 변수와 함수 그리고 데이터 구조로 합쳐질 수 있는 class의 특별한 instance를 일컷습니다. 


 object를 이해하기 위해 좋은 문구가 있어 가져왔습니다. 

  An object is similar to a structure, with the addition of method pointers, member access control, and an implicit data member which locates instances of the class (i.e. actual objects of that class) in the class hierarchy (essential for runtime inheritance features).


 class-based p에서는 object는 서브루틴에 의해 class로부터 만들어지고 생성자로부터 호출이 되며, 소멸자로부터 소멸됩니다. 그리고 여기서 다시 object는 class의 instance이고  class instance로 불립니다.

 JLS 4.3.1 Objects

An object is a class instance or an array.

The reference values (often just references) are pointers to these objects, and a

special null reference, which refers to no object.   

 한편 모든 class가 인스턴스화 될 수 있는 것은 아닙니다. 예를 들어 abstract class는 object가 안됩니다.




인스턴스란(instance)? 

(wiki 참고)"an instance is a specific realization of any object. " not an object!! but a realization!!

 instance는 형식적으로 object와 같은 의미를 갖는다고 합니다.(synonymous) 그리고 instance는 object의 구별되는 정체성을 강조한다고 합니다. 그래서 instance object라는 말로 쓰이기도 한다고 하네요.



자 여기까지 왔는데 class, object, instance 구별이 애매합니다.

object = class instance (JVM spec)이고 class는 template 이고(wiki) 앞으로 말할 instance는 object의 realization인데(wiki)!?!??! 뭔가 돌고 도는거 같은 상황... 그래서 저도 그렇고 많은 분들이 헷갈렸나 봅니다. (모든 is, are을  = 로 해석하는 것도 좋지 않지만  그걸 고려해도 헷갈립니다.)



정리하면 

class = 템플릿의 일종

object = 메모리의 위치 = class의 instance

instance = object의 특별한 realization 


뭔가 돌고 도는거 같은 느낌은 우리나라이기 때문이 아닙니다. stackoverflow 가보시면 많은 사람들이 헷갈려합니다.

JVM 과 우리나라 블로그의 설명의 한가지 분명한 차이점은 JVM에서는 instance를 쓴다면 홀로 쓰는 경우는 없고 class instance,  instance of method 이런 표현으로 씁니다. 꼭 instance를 class 와 object와 함께 동일 선상에 놓고 토론하는게 문제입니다.



아래는 oracle의 java tutorial 입니다.

https://docs.oracle.com/javase/tutorial/java/concepts/index.html

보시면 instance에 대한 설명은 없습니다. (tutorial 이지만)

 instance라는 용어는 독립적으로 쓰이지 않기 때문이죠. class instance  instance of method 이런 식입니다.

여기서 아시다시피 class instance는 object 인데 이때는 instance가 realization이라는 의미를 빌려 class 를 구체화 하여 object로 나타내고 있는 것입니다.


따라서 흔히 우리가 말하는 realization이라는 용어로 설명하는 instance는 곧 object입니다.


또 혼돈이 오는 것이 실생활에서 쓰이는 object의 의미입니다. object는 하나의 일반적인 대상을 가리키는 말로 자주 쓰이죠. '사람'을 예로 들면, 사람이라는 class는 틀로써 동물이라는 class를 상속받으며 이 틀을 통해 구체화한 하나의 일반적인 '사람'은 object이고 현실에 돌아다니는 사람1 사람2는 '사람'이라는 object의 instance다. 얼추 다 맞는 얘기 같습니다만 instance라는 용어가 문제가 되는 것입니다. 그리고 '사람'은 class 입니다.


 사람1, 사람2도 object입니다. 그리고 이는 곧 사람이라는 class의 instance 가 되고요. 



이제 instance는  해결이 된거 같네요.

남은 것은 class와 object의 차이를 더 분명히 하는 것입니다.


 object는 어디에 사는지 봅시다.

2.5.3 Heap 

The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated

 


class instance 와 array는 object라고 했습니다. 즉, object는 프로그램 동작 이후 heap 영역에 올라가게 됩니다. (갑자기 메모리 영역까지 건드려서 혼돈이 오지만 이해를 위해선 필요합니다.) heap 영역이란 c로 치면 대부분 static 변수나 전역변수들이 올라오는 메모리 영역인데 프로그램 시작시 할당되는 메모리 영역입니다. 자바에선 static 영역이 따로 있는 것으로 알고 있습니다. 정확히 알고싶으신 분은 jvm spec 문서에서 5장 loading linking and initializing 을 참고하시면 됩니다.






그러면 class는 어디에 살까요?  class file에 ? 아니면 램으로 올라올까요? 램에 올라가면 object 아닌가요?

우선 object가 되기전 class file에서의 class를 보겠습니다.

class 대신에 string으로 대체 하겠습니다. 

class file에서 string은 아래와 같이 구성되어야 하네요.



4.4.3 The CONSTANT_String_info Structure

The CONSTANT_String_info structure is used to represent constant objects of the

type String:

CONSTANT_String_info {

u1 tag;

u2 string_index;

}

The items of the CONSTANT_String_info structure are as follows:


tag

The tag item of the CONSTANT_String_info structure has the value

CONSTANT_String (8).

string_index

The value of the string_index item must be a valid index into the

constant_pool table. The constant_pool entry at that index must be a

CONSTANT_Utf8_info structure (§4.4.7) representing the sequence of Unicode

code points to which the String object is to be initialized.


4.4.7 The CONSTANT_Utf8_info Structure

The CONSTANT_Utf8_info structure is used to represent constant string values:

CONSTANT_Utf8_info {

u1 tag;

u2 length;

u1 bytes[length];

}

The items of the CONSTANT_Utf8_info structure are as follows: 



utf8 string 은 tag length bytes 로 구성되어 있네요. 

다음의 java 코드를 보시죠.


위와 같은 코드를 컴파일 하면 class file이 나옵니다. 

str, str1 str2 모두 "This..."라는 스트링을 말하고 있죠. (근데 그게 object는 같을지 다를지 그리고 constant string은 같을지 다를지 따져봐야겠죠?  근데 지금은 그게 중요한게 아니니... 패스)

그 class file을 디컴파일 해봤습니다.



뭔지는 모르겠지만 스트링이 여러개가 있습니다.  0100 으로 확인할 수 있죠...

그중 제가 생성할 스트링은 저어어기 주황색으로 있네요.

Tag, length, byte[] 로요.


아무튼 string 이 classfile에 이렇게 존재하듯이 class 도 classfile에 존재하겠네요! 

(class가 어떤 형식으로 있을 지는 JVM $4.4 The Constant Pool 에서 확인하세요.)


그런데 class가 이게 다일까요?? lass가 object가 되기 위해선 일부의 정보는 램으로 올라가야할거 같지 않습니까?

 JVM structure를 보겠습니다.


2. The Structure of the Java Virtual Machine

2.5 Run-Time Data Areas

     2.5.4 Method Area

The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.


    2.5.5 Run-Time Constant Pool

A run-time constant pool is a per-class or per-interface run-time representation of the constant_pool table in a class file (§4.4). It contains several kinds of constants, ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time. The run-time constant pool serves a function similar to that of a symbol table for a conventional programming language, although it contains a wider range of data than a typical symbol table.

Each run-time constant pool is allocated from the Java Virtual Machine's method area (§2.5.4). The run-time constant pool for a class or interface is constructed when the class or interface is created (§5.3) by the Java Virtual Machine.



구구 절절....

어쨌든 Program run-time 시에, JVM이 이런 두 가지 data 영역을 가지고 있습니다.

 Method Area는 Run Time Constant Pool (Pool이라 하죠)을 할당을 한다고 하고요.

 Run-Time Constant Pool 이라는게 있고 program이 런타임 시에 JVM에 있는 Pool에 각각의 class의 런타임 표현?값들을 담습니다. (이때 런타임 표현값들은 constant pool 로 봐도 되는 것 같습니다.)

 그러면 어떤 내용이 얼마만큼 저장이 될까요? 빨간 글을 보시면 run-time constant pool 에는 어떤 symbolic reference 들이 table로 있는데 pool이 그 table만 있지는 않답니다. constant pool이 전체다 올라가는게 아니라 symbolic reference 되어 있다네요.

 

그 다음  class loader가 저 reference를 따라가서 class file의 structure 대로 object를 heap에 생성하겠네요.


여기까지 입니다.



참고로 object에 대한 내용입니다. JVM은 object structure를 강제하지 않습니다. 맘대로 만들어 써라 이거겠죠.


2.7 Representation of Objects

The Java Virtual Machine does not mandate any particular internal structure for

objects.

In some of Oracle’s implementations of the Java Virtual Machine, a reference to a class

instance is a pointer to a handle that is itself a pair of pointers: one to a table containing

the methods of the object and a pointer to the Class object that represents the type of the

object, and the other to the memory allocated from the heap for the object data 





아쉽게도 실제 object는 보여드리지 못했습니다. 램어딘가 떠다니는 그녀석을 잡을 순 있겠지만 ... 이정도로만 하고 접어야죠.

만약 궁금하시면 5. Loading과 linking 그리고 initialization 을 참고하시면 되겠네요.



[마무리 정리]

이것저것 건드린게 많은데

처음 질문을 정리하면


class 는 틀로써 class file에 있다. JVM이 이를 참조해 object를 생성한다.

object는 class에 의해 만들어진 구체적인 대상으로 RAM에 있다.

instance는 어떤 대상의 관계에 초점을 맞춰서 표현하고 이해하는 것이 좋다. 왜냐하면 instance는 realization 이기 때문이다.  예를 들면, class instance 라는 표현이 있다.




끄읕.....




--------------------------------------------------------------------------------------------

아래는 그냥 공부하다 찾은 Resolution 이라는 용어 입니다. instance와 흡사한데 뭔가 다르군요.

컴파일 하다보면 unresolved 라는 에러가 나거든요. 여기 정의가 되어 있네요.

안드로이드 프로그래밍에서 R.java의 R이 Reference의 준말인지 Resolution의 준말인지 아니면 Resource 의 준말인지 알고 싶네요.