자바 문자열

JAVA 2015. 7. 26. 01:48

자바의 문자열은 String 이라는 특별한 시스템 클래스의 객체다. 

문자열을 손쉽게 문자 및 바이트 배열과 상호 변환 할 수 있지만

(내부적으로 char배열을 써서 문자열을 저장한다.), 

분명히 서로 다른 유형으로 구분된다. 

문자열에 들어있는 개별 문자는 직접 액세스 할 수 없으며(String b = "bbb"; b[2] // 이렇게 직접 접근 안되)

String클래스의 메소드를 써서 접근해야 한다. (b.at(2) 이런식)


자바 문자열은 변형 불가능하다(immutable)하다.

문자열을 조작하는 인스턴스도 사실 내부적으로는 새로운 문자열을 만들어서 반환하는 것이다. 

대신 필요에 따라 String 인스턴스로 변환 될 수 있는 변형 가능한 문자열을 만들어주는 

StringBuffer 와 StringBuilder 클래스가 있다. 

(StringBuffer는 모든 자바 버젼에서 사용 할 수 있고, thread-safe가 보장되지만,

StringBuilder는 자바 5에서 도입되었으며 thread-safe을 보장하지 못한다)


String인스턴스에서 + 연산자를 쓰면, 내부적으로 StringBuffer인스턴스를 사용하는데, 이 + 연산자를 쓸때는 

주의해서 쓰지 않으면 비효율적인 코드를 만들어 낼 가능성이 있다. 

다음의 코드와 같은 원리에 대해서 기억해둘 필요가 있겠다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// (1)
String s = "";
for(int i = 0;i<10;i++){
    s = s + i + " ";  
}
 
// (2)   (1)의 코드와 같다.
String s = "";
for(int i = 0;i<10;i++){
    StringBuffer t = new StringBuffer();
    t.append(s);
    t.append(i);
    t.append(" ");
    s = t.toString();  
}
 
// (3) 아래와 같이 만들어 주는 것이 훨씬 효율적이다.
StringBuffer b = new StringBuffer();
for(int i = 0;i<10;i++){
    b.append(i);
    b.append(' ');  
}
String s = b.toString();
 
cs


'JAVA' 카테고리의 다른 글

자바 리플랙션(Reflection) API  (0) 2015.08.05
자바 해시맵(HashMap)  (0) 2015.08.05
자바가 확장한 객체지향  (0) 2015.06.30
자바와 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
Posted by slender ankles
,

abstract키워드?

추상 메서드(Abstract Method)를 간단하게 설명하면 "선언부는 있는데 구현부가 없는 메서드"를 말한다.

추상 클래스(Abstract Class)는 "추상 메서드가 하나라도 있는 클래스는 추상클래스로 선언해야 한다"를 말한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Driver.java
package abstractMethod01;
 
public class Driver{
    public static void main(String[] args){
        동물[] 동물들 = new 동물[5];
        
        동물들[0= new 쥐();
        동물들[1= new 고양이();
        동물들[2= new 강아지();
        동물들[3= new 송아지();
        동물들[4= new 병아리();
        
        for(int i  = 0;i<동물들.length;i++){
            동물들[i].울어보세요();  
        }
    } 
}
 
// 쥐.java
package abstractMethod01;
public class 쥐 extends 동물{
    void 울어보세요(){
        System.out.println("찍!찍!");
    }  
}
 
// 고양이.java
package abstractMethod01;
public class 고양이 extends 동물{
    void 울어보세요(){
        System.out.println("야옹!");
    }  
}
 
// 병아리.java                           
package abstractMethod01;            
public class 병아리 extends 동물{        
    void 울어보세요(){               
        System.out.println("삐약");
    }                                
}
 
// 동물.java                                                               
package abstractMethod01;            
public class 동물{
    void 울어보세요(){               
        System.out.println("나는 동물 어떻게 울어야 하나요?");
    }                                
}
 
cs



동물타입의 참조 변수를 통해 하위 클래스의 인스턴스를 호출하고 있기 때문에 반드시 상위 클래스의

울어보세요()라는 메서드는 존재해야 한다. 

그런데, 동물클래스의 울어보세요()라는 메서드를 호출하게 되면 난감해진다.

동물이라는 객체를 울어보세요를 구현하기가 난감해진다. 


이럴 때 abstract 메서드를 사용하여 선언은 해놓되 구현부는 없는 형태로 구현한다.


1
2
3
4
5
// 동물.java
package abstractMethod01;
public abstract class 동물{
    abstract void 울어보세요();
}
cs


이렇게 되면 동물 클래스(최상위 추상 클래스)를 호출 할 때 에러가 난다. 

한마디로 추상클래스의 인스턴스 메서드를 호출하면 에러가 나므로 이러한 문제를 원천봉쇄 할 수 있다. 

- 추상클래스는 인스턴스, 즉 객체를 만들 수 없는 클래스가 된다.


- 추상클래스를 상속한 하위 클래스는 추상메서드의 구현부를 반드시 구현해야 한다.

그렇지 않은 경우에 "The type 고양이 must implement the inherited abstract method 동물.울어보세요()"라는 에러가 난다.


<<정리>>

- 추상 클래스는 인스턴스, 즉 객체를 만들 수 없다. 즉, new를 사용 할 수 없다.

- 추상 메서드는 하위 클래스에게 메서드의 구현을 강제한다. 오버라이딩 강제

- 추상 메서드를 포함하는 클래스는 반드시 추상 클래스여야 한다.


생성자란?

클래스의 인스턴스를 생성하는 메소드를 말한다.


클래스명 클래스참조변수 = new 클래스명();


생성자에 인자를 만들어도 되나?

된다. 

알아두어야 할 것이 있다.

- 개발자가 아무런 생성자도 만들지 않으면 자바는 인자가 없는 기본 생성자를 자동으로 만들어준다.

- 인자가 있는 생성자를 하나라도 만든다면 자바는 기본 생성자를 만들어 주지 않는다.


static 블록이란?

클래스가 스태틱 영역에 배치될 때 실행되는 코드 블록이다.

클래스의 생성자와 같은 기능이다. 

여러 개의 객체를 생성 할 때는 당연히 처음 클래스가 불려질 때 띄워지는 부분이라고 보면 된다.

코드를 보면

1
2
3
4
5
6
7
package staticblock;
public class 동물{
    static 동물{
        System.out.println("동물 클래스 레디 온");  
    }
}
 
cs



그렇다면 메모리 구조를 설명 할 때보면 처음에 클래스가 가장 먼저 올라간다고 했으니까 스태틱 블록이

main메서드보다 먼저 호출될까?

=> 아니다.

실제로는 해당 패키지 또는 클래스가 처음으로 사용 될 때 로딩되는 것이 맞다.


static블록이 실행 될 때

- 클래스의 정적 속성을 사용할 때

- 클래스의 정적 메서드를 사용할 때

- 클래스의 인스턴스를 만들 때


왜 구조를 설명 할 때보면 자바 어플리케이션 실행 가장 맨 처음에 스태틱영역에 클래스들이 자리 잡는다고 했는데 그렇지 않은가?

스태틱영역도 메모리이기 때문이다. 메모리는 최대한 늦게 시작하여 최대한 빠르게 반환하는 것이 효율적이다.

물론 자바의 구조상 클래스와 패키지들은 스태틱영역에 자리잡은채 반환되지는 않는다. 

하지만, 최대한 늦게 로딩함으로써 메모리 사용을 최대한 늦추기 위해서 이와 같이 동작한다.



final키워드란?(클래스, 변수, 메소드에서)

클래스에 final 키워드가 붙으면 어떤 의미인가?

=> 상속을 허락하지 않는다는 의미이다.

1
2
3
4
5
// 클래스에서의 final 키워드
package finalclass;
 
public final class 고양이{}
 
cs



변수에 final 키워드가 붙으면 어떤 의미인가?

=> 바로 변경 불가능한 상수가 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 변수에서의 final 키워드
 
package finalValuable;
 
public class 고양이{
    final static int 정적상수1 = 1;
    final static int 정적상수2;
    
    final int 객체상수1 = 1;
    final int 객체상수2;
    
    static{
        정적상수2 = 2;
        
        // 상수는 한 번 초기화되면 값을 변경할 수 없다.
        // 정적상수2 = 4;  
    }
    
    고양이(){
        객체상수2 = 2;
        // 상수는 한 번 초기화하면 값을 변경 할 수 없다.
        // 객체상수  2 = 4;
        
        final int 지역상수1 = 1;
        final int 지역상수2;
        
        지역상수2 = 2// 최초 한 번만 가능  
    }
}
 
cs


최초에 값을 할당하지 않은 변수인 경우에 최초 1회만 값을 할당 가능하다.


메소드에 final키워드가 붙으면 어떤 의미인가?

=> 최종이라는 의미로, 재정의, 즉 오버라이딩이 금지된다.


instanceof 연산자란?

인스턴스는 클래스를 통해 만들어진 객체이다. 

instanceof연산자는 만들어진 객체가 특정 클래스의 인스턴스인지 물어보는 연산자이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Driver.java
package instanceof01;
 
class 동물{
      
}
 
class 조류 extends 동물{
  
}
 
class 펭귄 extends 조류{
  
}
 
public class Driver{
    public static void main(String[] args){
        동물 동물객체 = new 동물();
        조류 조류객체 = new 조류();
        펭귄 펭귄객체 = new 펭귄();  
        
        System.out.println(동물객체 instanceof 동물); // true
        
        System.out.println(조류객체 instanceof 동물); // true
        System.out.println(조류객체 instanceof 조류); // true
        
        System.out.println(펭귄객체 instanceof 동물); // true
        System.out.println(펭귄객체 instanceof 조류); // true
        System.out.println(펭귄객체 instanceof 펭귄); // true
        
        System.out.println(펭귄객체 instanceof Object); // true
    }  
}
 
cs



- instanceof키워드는 실제 객체타입을 보고 판단한다.

- instanceof연산자는 클래스의 상속관계 뿐만 아니라 interface의 상속관계에서도 동일하게 적용된다.


package키워드란?

package키워드는 네임스페이스(이름공간)을 만들어주는 역할을 한다.

개발팀의 user클래스과 홍부팀의 user클래스는 분명 다르지만 같은 이름을 가진다. 

이러한 충돌을 막기 위하여 package키워드를 이용해  네임스페이스를 만들어주는 역할을 하는 것이다.


쉬운 예로)

A라는 사람의 스마트폰과 B라는 사람의 스마트폰은

스마트폰에는 동일하다. 하지만 A라는 사람과 B라는 사람의 이름이 다르기 때문에 

두 스마트폰을 구별할 수 있는 것이다.


interface키워드와 implements키워드 에서의 부가설명

앞써 설명했다. 접근제어지시자에 대해서 이야기하고자 한다.

- 인터페이스는 public 추상 메서드와 public 정적 상수만 가질 수 있다.

그렇다면 다음은 잘 못된 것인가?


1
2
3
4
5
6
interface Speakable{
double PI = 3.141592;
final double absoluteZeroPoint = -275.15;
 
void sayYes();
}
cs


=> 아니다. 배려깊게도 interface에 public과 abstract, static이라는 키워드를 사용하지 않아도 자동으로 그렇게 할당한다.

하지만 나는 이러한 특성을 알아도 반드시 명명해주겠다. 정확한 가독성이 중요하다고 생각하기 때문이다.


** 참고사항 **

자바 8에서의 변화 중 람다라는 것은 무엇인가?

좀 더 부가적인 설명이 필요하고 따로 정리해야겠지만, 

"람다는 변수에 저장 할 수 있는 로직이다."라고 설명 할 수 있다.

자바스크립트에서 변수에 함수를 저장하여 인자로 전달하거나 하는 기능을 사용 할 수 있었는데

자바에서도 이 같이 이해하면 될까?

다른 언어와 비교한다면

C++의 함수포인터!

C#의 델리게이트(Delegate)

자바스크립트 : 함수를 저장하는 변수 / 함수 인자로 callback 전달


this키워드?

- 지역 변수와 속성(객체 변수, 정적 변수)의 이름이 같은 경우 지역변수가 우선된다.

- 객체 변수와 이름이 같은 지역 변수가 있는 경우 객체 변수를 사용하려면 this를 접두사로 사용한다.

- 정적 변수와 이름이 같은 지역 변수가 있는 경우 정적 변수를 사용하려면 클래스명을 접두사로 사용한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package This;
 
class 펭귄{
    int var = 10;
    
    void test(){
        int var = 20;
        System.out.println(var);      // 20출력
        System.out.println(this.var); // 10출력
    }  
}
 
public class Driver{
    public static void main(String[] args){
        펭귄 뽀로로 = new 펭귄();
        뽀로로.test();  
    }  
}
 
cs



super키워드?

단일 상속만을 지원하는 자바에서 super는

"바로 위 상위 클래스의 인스턴스를 지칭하는 키워드"이다. 

- super 키워드란 ? => "바로 위 상위 클래스의 인스턴스를 지칭하는 키워드"

- 하지만, 상위의 상위 클래스 super.super로는 접근 할 수 없다.

'JAVA' 카테고리의 다른 글

자바 해시맵(HashMap)  (0) 2015.08.05
자바 문자열  (0) 2015.07.26
자바와 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
자바 메모리 구조 >>> 2  (0) 2015.06.30
Posted by slender ankles
,

자바와 객체지향

JAVA 2015. 6. 30. 15:45

구조적 프로그래밍?

아무리 복잡한 문제라도 작은 문제로 분할해서 하나씩 정복하다 보면 결국 해결된다는 전략입니다.

몇 천, 몇 만 라인을 논리적인 단위로 나누어 블록화해서 작성하자. 이런 논리적인 단위를 함수라고 합니다.


객체지향 프로그래밍?

함수를 이용한 프로그래밍이 좀 더 발전한 것이 객체지향 프로그래밍입니다.

세상 모든 눈으로 보여지는 것, 만져지는 것, 상상하는 것들을 객체로 판단해서 프로그래밍하는데 활용하겠다는 것.

- 세상의 존재하는 모든 것은 사물, 즉 객체(Object)이다.

- 각각의 사물은 고유하다.

- 사물은 속성을 갖는다.

- 사물은 행위를 한다.


사람은 사물을 하나하나 이해하기 보다는 분류(class)하고 싶어한다.

- 직립보행을 하며, 말을 하는 존재를 사람이라고 한다.

- 연미복, 짧은 다리, 날지 못하는 새를 펭귄이라고 한다.

- 밤하늘에 반짝이는 사물들을 별이라고 한다.


더 나아가, 

객체? 속성? 메소드?

김연아(Object), 유재석(Object), 하하(Object), 강호동(Object) 등등

이런 사람이라는 객체들은 나이(Property), 몸무게(Property), 키(Property)와 같은 속성과

싸다(Method), 먹다(Method), 말하다(Method), 일하다(Method)와 같은 메소드를 가지고 있다.


객체 지향 이전 vs 객체 지향

객체 지향 이전에는 객체에 대한 속성과 메소드를 따로 구분하여 구현하였는데 반해,

객체 지향에서는 이런 속성(필드), 메소드(함수)를 합하여 객체화 시켜 구현을 하게 한다.


클래스와 객체와의 관계

클래스

분류이다. 

객체 

실체이다.

객체지향적 관점에서 사람은 클래스이고, 김연아는 객체이다.


클래스와 객체를 구분하는 간단한 방법

나이를 물어보는 것이다.

사람이 몇 살인가? => (X) 

김연아는 몇 살인가? => (O)

펭귄은 몇 살인가? => (X)

뽀로로는 몇 살인가? => (O)

김연아와 뽀로로는 몇 살인지 답변 가능하다. 그러므로 객체이다.

하지만 사람과 펭귄의 나이를 물어보는 것은 무엇인가 이상하다. 이 것은 클래스(분류)이다.


객체지향의 4대 특징? 

추상화, 상속, 캡슐화, 다형성



추상화(Abstraction)란?

객체에 대한 속성이나 특성을 가지고 모델링하는 것을 말한다.

ex) 환자라는 객체에 대한 추상화

환자라는 객체에 대해 추상화하기 위해서는 환자에 대한 속성이나 특성을 가지고 모델링하는 것을 말한다.

환자의 이름, 나이, 몸무게, 기저질환유무라는 속성(Property)와

운동하다, 운전하다, 화장실가다, 밥먹다와 같은 메소드(Method)로 추상화 할 수 있을 것이다.

환자라는 것에 국한한다는 것은 프로그래밍에서는 애플리케이션의 경계로부터 정한다고 한다.


=> 애플리케이션의 경계안에서 객체에 대한 속성이나 특성을 가지고 모델링하는 것을 말한다.

라고 정의할 수 있겠다.




클래스를 통해 객체를 만들어 낼 때의 메모리 구조는 어떻게 변화하나?


Mouse mickey = new Mouse();


3개의 명령문이 녹아있다.

Mouse mickey // Mouse객체에 대한 참조 변수 mickey를 만든다.

new Mouse() // Mouse클래스의 인스턴스를 하나 만들어 힙에 배치한다.

= 대입문 // Mouse객체애 대한 주소(포인터)를 참조 변수 mickey에 할당한다.




Mouse라는 클래스는 스태틱영역에 위치해있다.

new Mouse()라는 명령어를 만나면 인스턴스를 만들어 힙 영역에 배치한다.

또 지역 변수인 mickey라는 변수는 힙영역의 인스턴스를 가리키고 있는 모양이다.





클래스 멤버 vs 객체 멤버 = static 멤버 vs 인스턴스 멤버


static 키워드란 무엇을 말하는가?

미키마우스, 제리마우스, 마이티마우스란 객체에서 공통된 질문인 "꼬리가 몇 개인가?"를 해보자.

무조건 답은 "하나"이다. 마우스라는 클래스의 공통된 성질이다. 꼬리가 한 개 인 것.

그렇다면 이렇게 모든 객체가 가진 공통된 특성을 힙영역에 메모리를 잡고 할 당하고 있는 것은 낭비가 아닌가?

countofTail과 같은 변수를 스태틱 변수로 옮겨 버리면 메모리를 더욱 효율적으로 사용 할 수 있다.

변수 앞에 static이라는 키워드를 붙여서 사용한다.

static 멤버는 클래스의 공통된 특성을 가진 변수를 스태틱 영역에 할당하는 것을 말한다.



static변수에 접근하는 효율적인 방법은?

mickey라는 참조변수는 Mouse라는 객체에 도달한 후에 다시 스택틱 변수가 위치한 스태틱 영역으로 이동한다.

(스택영역 -> 힙 영역 -> 스태틱영역)

하지만 클래스명.정적멤버  형식으로 접근하게 되면 스택에서 바로 스태틱영역으로 접근하여 효율적이다.

(스택영역 -> 스태틱영역)


인스턴스 멤버는

힙 영역에 할당된 객체들의 멤버를 말한다.


클래스 멤버 = static 멤버 = 정적 멤버

객체 멤버 = 인스턴스 멤버

용어에 대해 부르는 것들이 조금 다양할 뿐 같은 말이다. 헷갈리지 말아야 한다.







상속(Inheritance)이란? => 재사용 + 확장

상속에 대한 정의는 상위 클래스를 하위 클래스가 재사용하고 확장할 수 있는 특징을 말한다.

보통 부모클래스, 자식클래스로 나누는데 이러한 용어보다는 

상위 클래스 - 하위 클래스 또는 슈퍼 클래스 - 서브 클래스 라고 하는 것이 맞다.

이러한 관점은 계층적인 관점이 아니라, 분류적인 관점이기 때문이다.


이러한 주장을 뒷받침하듯이 자바의 문법은 Inheritance가 아닌 extends(확장하다)라는 키워드를 사용한다.



toString()이라는 메서드를 어느 클래스에서든지 사용 할 수 있는 이유는?

모든 클래스의 상속 구조에서의 최상위 클래스는 Object클래스이다.

결국 모든 클래스는 Object클래스의 특성을 물려받는다.

상속때문이다. 상속의 강력한 기능을 잘 표현한 예라고 할 수 있다.


상속관계를 맺기 위한 조건?

is a kind of의 조건을 만족해야 한다.

하위클래스 is a kind of 상위클래스 => 하위클래스는 상위 클래스의 한 종류이다?

펭귄 is a kind of 동물 => 펭귄은 동물의 한 종류이다. 

고래 is a kind of 동물 => 고래는 동물의 한 종류이다.

조류 is a kind of 동물 => 조류는 동물의 한 종류이다.


자바가 다중 상속을 막은 이유는?

자바는 C++과 다르게 다중 상속을 포기했다. 

다중 상속의 여러 문제점 때문에 다중 상속을 지원하지 않게 되었다. 

다이아몬드 문제

TopA

MiddleB, middleC

BottomD

B는 A를 상속했다. C도 A를 상속했다.

D는 B와 C를 다중 상속했다. 

=> A가 가지고 있는 공통된 특성이 중복으로 D가 가져야 된다.


그럼 자바는 다중 상속을 어떻게 보완했나? => Interface

다중 상속을 포기하고 인터페이스를 도입한 자바에서 인터페이스는 어떤 역할을 하며 어떤 관계를 나타내는 것인가?

- 인터페이스 : 구현 클래스 is able to 인터페이스

- 해석 : 구현 클래스는 인터페이스 할 수 있다.

- 예제 : 고래는 헤엄 칠 수 있다.




위의 관계도를 보면서 다중상속의 단점을 버리고, 이점을 취한 인터페이스에 대한 이해를 할 수 있겠다.


인터페이스는 be able to, 즉 "무엇을 할 수 있는"이라는 표현 형태로 만드는 것이 좋다.

자바 API에서도 이러한 be able to 형식의 인터페이스를 많이 볼 수 있다.

Serializable 인터페이스(직렬화 할 수 있는)

Cloneable 인터페이스(복제 할 수 있는)

Comparable 인터페이스(비교 할 수 있는)

Runnable 인터페이스(실행 할 수 있는)



// 동물.java
package inheritance02;
 
public class 동물{
    String myClass;
    
    동물(){
        myClass = "동물";  
    }
    void showMe(){
        System.out.println(myClass);  
    }
}
 
// 날수있는.java
package inheritance02;
 
public interface 날수있는{
    void fly();
}
 
// 헤엄칠수있는.java
package inheritance02;
 
public interface 헤엄칠수있는{
    void swim();
}
 
// 포유류.java
package inheritance02;
 
public class 포유류 extends 동물{
    포유류(){
        myClass = "포유류";  
    }
}
 
// 조류.java
package inheritance02;
 
public class 조류 extends 동물{
    조류(){
        myClass = "조류";
    }
}
 
// 고래.java
package inheritance02;
 
public class 고래 extends 포유류 implements 헤엄칠 수 있는{
    고래(){
        myClass = "고래";  
    } 
    
    @Override
    public void swim(){
        System.out.println(myClass + "수영 중 어프!! 어프!!");
    } 
}
 
// 박쥐.java
package inheritance02;
 
public class 박쥐 extends 포유류 implements 날 수 있는{
    박쥐(){
        myClass = "박쥐";  
    } 
    
    @Override
    public void fly(){
        System.out.println(myClass + "날고 있다..슈융");
    } 
}
 
cs


상속될 때의 메모리 구조는 어떻게 되나?

상속 받은 상위 클래스까지 힙 영역에 할당된다.







다형성 : 사용편의성


오버라이딩(Overriding) vs 오버로딩(Overloading)

- 라이딩 : 올라타기

- 로딩 : 적재하기


오버 라이딩 => 재정의 : 상위 클래스의 같은 메서드 이름, 같은 인자 리스트

오버 로딩 => 중복정의 : 상위 클래스의 같은 메서드 이름, 다른 인자 리스트




** 기억해야 되는 부분

상위 클래스의 객체 참조 변수를 사용하면 재정의하지 않은 메서드가 불려지나?

상위 클래스의 객체 참조 변수를 사용하더라도 하위 클래스에서 오버라이딩(재정의)한 메서드가 호출 된다는 점을 기억해야 한다.


다형성이 지원되지 않는다면?

예를 들어 연산하는 부분을 생각해볼 수 있다. 

자바와 같은 경우에 정수 자료형으로 byte, short, int, long, char 부동소수점 수 자료형으로는 float, double이 있다. 

만약 다형성이 지원되지 않는다면 다른 함수 이름을 7 * 7 = 49개 정도는 만들어줘야 한다.

다형성이 지원하기 때문에 하나의 메서드를 가지고 이 같은 필요를 충족시켜줄 수 있게 된다.



캡슐화란 무엇인가? 정보은닉이란 무엇인가?

객체지향의 특징 중 캡슐화란 접근 제어 지시자를 이용해 외부로부터 정보를 마구잡이로 접근 할 수 없게끔 할 수 있는 특징을 말한다.

긴설명은 생략하고 정확하게 이해하고 있고, 실전을 통해서 익혀야 한다고 생각한다.

간략히 표현하자면, 


그 동안 실수로 알았던 것이 

Protected가 상속 받은 클래스에서만 접근 가능한 줄 알았는데 같은 패키지에서도 접근 가능하다는 것이다.



참조변수의 복사?

Call By Value vs Call By Reference

참조 변수를 복사하는 것은 결국 주소를 복사하는 것이다.

String 변수에 대한 CBV, CBR에 대해서 설명해보겠다.


String a = "aaa";


String b = a;


String c = new String("aaa");


a와 b는 같은 주소값을 가진다. 

c는 새로운 주소에 값이 할당된다.

그래서 == 연산자로 비교하면 a와 b는 같다

하지만 a와 c, b와 c를 비교하면 다르다.


== 연산자는 주소 값을 비교하고, equals()라는 함수를 통해 값을 비교 할 수 있다. 

CBV와 CBR의 예라고 할 수 있다. 

'JAVA' 카테고리의 다른 글

자바 문자열  (0) 2015.07.26
자바가 확장한 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
자바 메모리 구조 >>> 2  (0) 2015.06.30
자바 메모리 구조>>1  (0) 2015.06.30
Posted by slender ankles
,

자바 스레드의 이해

JAVA 2015. 6. 30. 15:44

앞써 설명한 자바의 메모리 구조에서 


T메모리 구조(스태틱영역, 스택영역, 힙영역으로 구성되는 것을 그냥 T메모리 구조라고 부름)에 대해서 설명했다.





스레드란 무엇인가?

스레드는 스택영역을 스레드의 개수만큼 분할하는 것이다.

또한 각각의 스레드는 다시 스태틱영역, 스택영역, 힙영역을 가지게 된다.

스택영역이 분할되므로 스레드 간의 스택영역을 침범 할 수는 없지만 

큰 측면에서 봤을 때 결국 자바 메모리의 스태틱영역과 힙영역은 공유 할 수 있다!


멀티프로세스 vs 멀티스레드


멀티 프로세스(Multi Process)

하나의 프로세스가 다른 프로세스의 T메모리 영역을 절대 침범 할 수 없는 메모리로써 안전한 구조이지만, 그만큼 메모리 사용량을 크다!


멀티 스레드(Multi Thread)

스택영역이 분할되어 하나의 스레드에서 다른 스레드로 접근 할 수는 없지만 스태틱 영역과 힙 영역은 공유해서 사용 할 수 있다. 따라서 멀티 프로세스 대비 메모리를 적게 사용 할 수 있는 구조이다.


서버 프로그래밍에서 Servlet은 요청 당 스레드를 생성한다고 들어봤다

** Servlet 과 CGI??

요청 당 스레드를 생성 => Servlet

요청 당 프로세스 생성 => CGI


OS시간에도 배웠지만 

스레드가 Critical Section을 접근하는 것에 대한 문제를 해결해야 한다.

다음과 같은 문제가 있다.

 스레드1

 스레드2

 

 전역변수 A에 10 할당

 

 전역변수 A는 10을 저장

 

 전역 변수 A에 20할당

 전역변수 A는 20을 저장

 전역변수 A의 값 출력

 

 전역변수 A는 20을 출력


스레드1이 A에 분명 10을 할당했는데, 후에 바로 스레드2가 20을 할당해버리므로

예상치 못한 결과를 얻어낸다.


이러한 공유 자원을 관리하는 자바만의 방법이 있는지 알아보고 후에 글을 적겠다.

'JAVA' 카테고리의 다른 글

자바가 확장한 객체지향  (0) 2015.06.30
자바와 객체지향  (0) 2015.06.30
자바 메모리 구조 >>> 2  (0) 2015.06.30
자바 메모리 구조>>1  (0) 2015.06.30
GC - Garbage Collection 이란?  (0) 2015.06.30
Posted by slender ankles
,

자바 메모리 구조 >>> 2

JAVA 2015. 6. 30. 15:44

자바 프로그램의 구동 환경에 대해서 다시 한 번 정리하고자 한다.

자바개발도구 JDK , 자바실행환경 JRE, 자바가상기계 JVM 으로 이루어져 있다.




간단히 말해서 자바 개발 도구로 개발된 프로그램이

자바실행환경에서 해석되어 자바가상기계 위에서 동작하는 것이다.

당연 플랫폼에 종속적이지 않는 장점을 가지게 된다.

(윈도우, 리눅스 등 OS에 영향 없이 한 개의 코드로 모두 실행 가능하다)


이를 그림으로 나타내면 다음과 같다.




보통의 프로그램들에서의 메모리 구조는


코드실행영역과 데이터 저장 영역으로 나뉜다.


자바와 같은 객체 지향 프로그램에서는 다음과 같이 데이터 저장 영역이


1) 스태틱 영역(클래스들의 놀이터)

2) 스택 영역(메서드들의 놀이터)

3) 힙 영역(객체들의 놀이터)


으로 나뉜다.








** "Hello World"라는 것을 출력하는 프로그램을 통해 JVM이 어떻게 프로그램을 구동시키는 지에 대해서 알아보겠다.




1) 자바 프로그램이 시작하여 먼저 main()함수가 있는지를 확인 한 후에

전처리 과정을 실시한다. 전처리 과정이라함은 자바에 반드시 포함되는 java.lang클래스를 스태틱영역에 올리는 것이다.그리고 개발자가 만든  클래스들과 import한 클래스들을 스태틱영역에 올린다.





2) 스택영역에 main함수가 할당된다.

3) 스택영역에 main함수의 인자인 args가 할당된다.






4) println과 같은 메소드는 메모리 구조에 큰 변화가 일어나지 않지만 GPU를 통해 화면에 출력하는 동작을 하게 된다.





5) } 이라는 main()메소드의 끝과 함께 스택영역에 할당된 스택프레임이 소멸된다.




* Main()메서드가 스택영역에 올라가면서 주요 로직이 동작하게 된다.



와 같은 코드에서도 순서대로 


1) i라는 변수가 스택에 할당(현재 쓰레기값)

2) i에 20이 할당

3) j 라는 변수가 스택에 할당

4) j라는 변수에 30이 할당

5) i 에 i의 값과 j의 값이 합해짐

main()메서드 종료되면서 없어짐


과 같이 동작하게 된다.


static 변수 즉 전역 변수는 static영역에 할당된다.

'JAVA' 카테고리의 다른 글

자바가 확장한 객체지향  (0) 2015.06.30
자바와 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
자바 메모리 구조>>1  (0) 2015.06.30
GC - Garbage Collection 이란?  (0) 2015.06.30
Posted by slender ankles
,

자바 메모리 구조>>1

JAVA 2015. 6. 30. 15:43

자바를 시작하기에 앞서 자바의 메모리의 구조에 대해서 알아야한다.

자바의 메모리 구조를 통해서 자바만이 가지고 있는 identity(아이덴티티)에 대해서 알아본다면 

자바를 탄탄하게 시작 할 수 있을 것이라 생각한다.



1. 자바 버츄얼 머신(Java Virtual Machine, JVM)이란 무엇이며, 그 특징이 무엇인지에 대해서 알아본다.

JVM하면 떠오르는 것은 플랫폼 종속적이지 않은 자바의 특징을 보여주는 것...정도로만 알고 있었다. 

JVM은 자바로 만들어진 모든 프로그램(일반 어플리케이션, Web Application Server(WAS) 등)을 실행하는 역할을 한다. 구별하지 않고 모든 자바 프로그램들은 JVM을 거쳐야 한다는 것이다. 

JVM이 왜 자바의 핵심인지가 설명 할 수 있는 대목


JVM이 가지고 있는 특징은 

1) 스택기반 가상머신이란?

대표적인 컴퓨터 아키텍처인 인텔 x86 아키텍처나 ARM 아키텍처와 같은 하드웨어가 레지스터 기반으로 동작하는 데 비해 JVM은 스택 기반으로 동작한다.

2) 심볼릭 레퍼런스

기본 자료형(primitive data type)을 제외한 모든 타입(클래스와 인터페이스)을 명시적인 메모리 주소 기반의 레퍼런스가 아니라 심볼릭 레퍼런스를 통해 참조한다.

3) 가비지 컬렉션(Garbage Collection)

클래스 인스턴스는 사용자 코드에 의해 명시적으로 생성되고 가비지 컬렉션에 의해 자동으로 파괴된다.

4) 기본 자료형을 명확하게 정의하여 플랫폼 독립성 보장

C/C++ 등의 전통적인 언어는 플랫폼에 따라 int 형의 크기가 변한다. JVM은 기본 자료형을 명확하게 정의하여 호환성을 유지하고 플랫폼 독립성을 보장한다.

5) 네트워크 바이트 오더(Network Byte Order)

자바 클래스 파일은 네트워크 바이트 오더를 사용한다. 인텔 x86 아키텍처가 사용하는 리틀 엔디안이나, RISC 계열 아키텍처가 주로 사용하는 빅 엔디안 사이에서 플랫폼 독립성을 유지하려면 고정된 바이트 오더를 유지해야 하므로 네트워크 전송 시에 사용하는 바이트 오더인 네트워크 바이트 오더를 사용한다. 네트워크 바이트 오더는 빅 엔디안이다.



자바의 환경!







2. JVM에 의해 자바 메모리 구조가 어떻게 작동되는지에 대해서 알아야 한다.

JVM이 어떤식의 구조로 되어 있고, 이를 통해 Java GC가 어떻게 일어나는지에 대해서 이해할 수 있게 될 것이다.



[자바 프로그램]

Java에서 프로그램을 실행한다는 것은 Class 파일을 JVM으로 로딩하고 ByteCode를 해석(Interpret)하는 작업은 물론,

메모리 등의 리소스를 할당하고 관리하며 정보를 처리하는 일련의 작업들을 포괄한다. 

이 때 JVM은 스레드 관리 및 Garbage Collection과 같은 메모리 재생 작업도 수행한다. 



[JVM의 기본적인 수행과정]

1. Class Loader System을 통해 Class 파일들을 JVM으로 로딩한다.

2. 로딩된 Class 파일들을 Execution Engine을 통해 해석한다. 

3. 해석된 프로그램은 Runtime Data Areas에 배치되어 실질적인 수행이 이루어지게 된다. 이러한 실행 과정 속에서 JVM 은 필요에 따라 Thread Synchronization과 Garbage Collection(GC)와 같은 관리작업을 수행하게 된다. 



클래스 로더(Class Loader)가 컴파일된 자바 바이트코드를 런타임 데이터 영역(Runtime Data Areas)에 로드하고, 실행 엔진(Execution Engine)이 자바 바이트코드를 실행한다.


클래스 로더

자바는 동적 로드, 즉 컴파일타임이 아니라 런타임에 클래스를 처음으로 참조할 때 해당 클래스를 로드하고 링크하는 특징이 있다. 이 동적 로드를 담당하는 부분이 JVM의 클래스 로더이다. 

런타임 데이터 영역

런타임 데이터 영역은 JVM이라는 프로그램이 운영체제 위에서 실행되면서 할당받는 메모리 영역이다. 런타임 데이터 영역은 6개의 영역으로 나눌 수 있다. 이중 PC 레지스터(PC Register), JVM 스택(JVM Stack), 네이티브 메서드 스택(Native Method Stack)은 스레드마다 하나씩 생성되며 힙(Heap), 메서드 영역(Method Area), 런타임 상수 풀(Runtime Constant Pool)은 모든 스레드가 공유해서 사용한다.


  • PC 레지스터: PC(Program Counter) 레지스터는 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 생성된다. PC 레지스터는 현재 수행 중인 JVM 명령의 주소를 갖는다.
  • JVM 스택: JVM 스택은 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 생성된다. 스택 프레임(Stack Frame)이라는 구조체를 저장하는 스택으로, JVM은 오직 JVM 스택에 스택 프레임을 추가하고(push) 제거하는(pop) 동작만 수행한다. 예외 발생 시 printStackTrace() 등의 메서드로 보여주는 Stack Trace의 각 라인은 하나의 스택 프레임을 표현한다.
  • 스택 프레임: JVM 내에서 메서드가 수행될 때마다 하나의 스택 프레임이 생성되어 해당 스레드의 JVM 스택에 추가되고 메서드가 종료되면 스택 프레임이 제거된다. 각 스택 프레임은 지역 변수 배열(Local Variable Array), 피연산자 스택(Operand Stack), 현재 실행 중인 메서드가 속한 클래스의 런타임 상수 풀에 대한 레퍼런스를 갖는다. 지역 변수 배열, 피연산자 스택의 크기는 컴파일 시에 결정되기 때문에 스택 프레임의 크기도 메서드에 따라 크기가 고정된다.
  • 지역 변수 배열: 0부터 시작하는 인덱스를 가진 배열이다. 0은 메서드가 속한 클래스 인스턴스의 this 레퍼런스이고, 1부터는 메서드에 전달된 파라미터들이 저장되며, 메서드 파라미터 이후에는 메서드의 지역 변수들이 저장된다.
  • 피연산자 스택: 메서드의 실제 작업 공간이다. 각 메서드는 피연산자 스택과 지역 변수 배열 사이에서 데이터를 교환하고, 다른 메서드 호출 결과를 추가하거나(push) 꺼낸다(pop). 피연산자 스택 공간이 얼마나 필요한지는 컴파일할 때 결정할 수 있으므로, 피연산자 스택의 크기도 컴파일 시에 결정된다.

  • 네이티브 메서드 스택: 자바 외의 언어로 작성된 네이티브 코드를 위한 스택이다. 즉, JNI(Java Native Interface)를 통해 호출하는 C/C++ 등의 코드를 수행하기 위한 스택으로, 언어에 맞게 C 스택이나 C++ 스택이 생성된다.

  • 메서드 영역: 메서드 영역은 모든 스레드가 공유하는 영역으로 JVM이 시작될 때 생성된다. JVM이 읽어 들인 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드와 메서드 정보, Static 변수, 메서드의 바이트코드 등을 보관한다. 메서드 영역은 JVM 벤더마다 다양한 형태로 구현할 수 있으며, 오라클 핫스팟 JVM(HotSpot JVM)에서는 흔히 Permanent Area, 혹은 Permanent Generation(PermGen)이라고 불린다. 메서드 영역에 대한 가비지 컬렉션은 JVM 벤더의 선택 사항이다.
  • 런타임 상수 풀: 클래스 파일 포맷에서 constant_pool 테이블에 해당하는 영역이다. 메서드 영역에 포함되는 영역이긴 하지만, JVM 동작에서 가장 핵심적인 역할을 수행하는 곳이기 때문에 JVM 명세에서도 따로 중요하게 기술한다. 각 클래스와 인터페이스의 상수뿐만 아니라, 메서드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블이다. 즉, 어떤 메서드나 필드를 참조할 때 JVM은 런타임 상수 풀을 통해 해당 메서드나 필드의 실제 메모리상 주소를 찾아서 참조한다.
  • 힙: 인스턴스 또는 객체를 저장하는 공간으로 가비지 컬렉션 대상이다. JVM 성능 등의 이슈에서 가장 많이 언급되는 공간이다. 힙 구성 방식이나 가비지 컬렉션 방법 등은 JVM 벤더의 재량이다.

실행 엔진

클래스 로더를 통해 JVM 내의 런타임 데이터 영역에 배치된 바이트코드는 실행 엔진에 의해 실행된다. 실행 엔진은 자바 바이트코드를 명령어 단위로 읽어서 실행한다. CPU가 기계 명령어을 하나씩 실행하는 것과 비슷하다. 바이트코드의 각 명령어는 1바이트짜리 OpCode와 추가 피연산자로 이루어져 있으며, 실행 엔진은 하나의 OpCode를 가져와서 피연산자와 함께 작업을 수행한 다음, 다음 OpCode를 수행하는 식으로 동작한다.

그런데 자바 바이트코드는 기계가 바로 수행할 수 있는 언어보다는 비교적 인간이 보기 편한 형태로 기술된 것이다. 그래서 실행 엔진은 이와 같은 바이트코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경하며, 그 방식은 다음 두 가지가 있다.

  • 인터프리터: 바이트코드 명령어를 하나씩 읽어서 해석하고 실행한다. 하나씩 해석하고 실행하기 때문에 바이트코드 하나하나의 해석은 빠른 대신 인터프리팅 결과의 실행은 느리다는 단점을 가지고 있다. 흔히 얘기하는 인터프리터 언어의 단점을 그대로 가지는 것이다. 즉, 바이트코드라는 '언어'는 기본적으로 인터프리터 방식으로 동작한다.
  • JIT(Just-In-Time) 컴파일러: 인터프리터의 단점을 보완하기 위해 도입된 것이 JIT 컴파일러이다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅하지 않고 네이티브 코드로 직접 실행하는 방식이다. 네이티브 코드를 실행하는 것이 하나씩 인터프리팅하는 것보다 빠르고, 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 계속 빠르게 수행되게 된다.

JIT 컴파일러가 컴파일하는 과정은 바이트코드를 하나씩 인터프리팅하는 것보다 훨씬 오래 걸리므로, 만약 한 번만 실행되는 코드라면 컴파일하지 않고 인터프리팅하는 것이 훨씬 유리하다. 따라서, JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 정도를 넘을 때에만 컴파일을 수행한다.


자바가 느리다고 하는 이유?





'JAVA' 카테고리의 다른 글

자바가 확장한 객체지향  (0) 2015.06.30
자바와 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
자바 메모리 구조 >>> 2  (0) 2015.06.30
GC - Garbage Collection 이란?  (0) 2015.06.30
Posted by slender ankles
,

<참조 - 네이버 개발자 센터 - http://helloworld.naver.com/helloworld/1329>


gc(garbage collection)이란?

gc에 대해 알기 위해서는 stop-the-world 라는 것에 대해서 알아야한다.

stop-the-world란 gc를 실행하기 위해서 jvm애플리케이션이 실행을 멈추는 것이다

gc를 실행하는 스레드를 제외한 모든 스레드는 정지한다. 

결국 gc 튜닝이란 stop-the-world의 시간을 최소로 하는 것을 말한다고 할 수 있다. 


자바 프로그램에서는 메모리를 명시적으로 지정하여 해제 할 수 없다. 

해당 객체를 null로 지정하거나 (이 것은 큰 문제는 안됨)

system.gc()와 같은 함수를 사용하는 방법은 있으나 사용하면 안 된다. 

성능에 지대한 영향을 끼치기 때문이다.


자바코드에서는 메모리를 명시적으로 해제하지 않기때문에 가비지컬렉터가 더 이상 필요 없는 객체를 지우는 것이다.


가비지 컬렉터(Garbage Collector)는 두 가지 가설에 의해서 만들어졌다. 

이 가설을 "Weak generational hypothesis"라고 하는데

 * 대부분의 객체는 금방 접근 불가능한 상태가 된다. 

 * 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.


이러한 가설의 장점을 최대한 살리기 위해서 Hospot VM에서는 크게 2개의 물리적 공간으로 나누었다. 


Young영역과 Old영역


Young영역은 무엇인가?

새롭게 생성한 객체의 대부분이 여기에 위치한다. 

대부분의 객체가 금방 접근 불가능한 상태가 되기 때문에 많은 객체가 Young영역에 생성되었다가 사라진다.

이 영역에서 객체가 사라질 때 minor GC라고 한다.


Old영역은 무엇인가?

접근 불가능한 상태로 되지 않아 Young영역에서 살아남은 객체들이 이 곳으로 복사된다. 

대부분 Young영역보다 크게 할당하며, 크게 할당된만큼 Young영역보다는 GC가 적게 일어난다.

이 영역에서 객체가 사라질 때 major GC(혹은 Full GC)가 발생한다고 한다.



 

Permanent Generation 영역은 무엇인가?

영원한 영역이라는 말은 아니다. 

객체나 억류된(intern)된 문자열 정보를 저장하는 곳이며, 여기서 GC가 일어나도 

major GC가 일어났다고 한다.





Old 영역에서 Young 영역으로 참조하고 있는경우에는 어떻게 처리하나?

=> 그래서 old영역에는 카드테이블(card table)이 존재한다. 

카드테이블은 Old영역에서 Young영역으로 참조하고 있는 정보를 담고 있으므로

모든 old영역의 참조를 뒤져본 후에 GC가 일어나는것이 아니라 카드테이블정보만 

보고 GC가 일어나게 되는 것이다. 



young 영역은 어떻게 구성되는가?

Eden영역과 survivor영역 2개로 구성된다. 총 3개의 영역으로 구성된다.


새로 생성된 객체는 Eden영역에 위치한다

Eden영역에서 GC가 한번 일어난 후에 살아남은 객체는 Survivor영역 중에 하나로 이동한다.

Eden영역에서 GC가 발생할 때마다 Survivor영역에는 살아남은 객체가 쌓이게 된다.

하나의 survivor영역이 가득차게 되면 모든 객체가 다른 survivor영역으로 이동하게 된다. 원래있던 survivor영역은 비어있는 상태가 된다.

- 이 과정을 반복하다가 계속해서 살아남아 있는 개체는 Old영역으로 이동하게 된다. 



이 메커니즘에 대해서 이해 하게 되면 

두 survivor영역에 모두 객체가 있거나, 두 영역 모두 사용량이 0이라면 시스템은 정상적이지 않다는 것을 판단 할 수 있게 된다. 


그렇다면 Old영역에서의 GC는 어떤 과정으로 처리되나?

기본적으로 Old영역이 가득차게 되면 GC가 일어난다. 

Old영역에서의 GC는 JDK 7 기준으로 5가지가 지원된다.

- serial GC

- parallel GC

- parallel Old GC

- Concurrent Mark & Sweep GC(이하 CMS)

- G1(Garbage First) GC


이 중에서 반드시 알아야 할 것은 운영서버에서는 serial GC를 절대 사용하면 안된다는 것이다. 


Serial GC는 어떤 방식으로 이루어지나?

Young영역에 대한 GC는 앞에 설명한 바와 같이 이루어진다. 

Old영역에서의 GC는 기본적으로 mark-sweep-compact라는 알고리즘을 사용한다. 


이 알고리즘의 첫 단계는 Old 영역에 살아 있는 객체를 식별(Mark)하는 것이다. 

그 다음에는 힙(heap)의 앞 부분부터 확인하여 살아 있는 것만 남긴다(Sweep)

마지막 단계에서는 각 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채워서 객체가 존재하는 부분과 객체가 없는 부분으로 나눈다(Compaction).


Serial GC는 적은 메모리와 CPU 코어 개수가 적을 때 적합한 방식이다.


Parallel GC

Parallel GC는 Serial GC와 기본적인 알고리즘이 동일하다. 

그러나 Serial GC는 스레드가 한 개인것에 비해 Parallel GC에 쓰이는 스레드는 여러개다.

그래서 시리얼GC보다 더 빠르게 처리가 가능한 것이다. 


- parallel Old GC란?


- Concurrent Mark & Sweep GC 란?


- G1(Garbage first) GC 란?



****정리****

고급 개발자라는 것은 GC에 대한 명확한 이해와 함께 GC를 튜닝하는 관심과 능력을 가지고 있어야 된다고 한다. 

(네이버 개발자 센터에서 이 글의 원본을 쓰신 분이 한 말)

결국 대용량이나 거대한 프로젝트를 접해보신 분이 이러한 GC 튜닝을 해봐야겠다는 마음도 생겼기 때문이다. 

앞서 JDK에서 여러가지 GC를 제공하는 이유인 즉슨 가장 좋은 GC는 없다는 것이다. 그 서버의 상황과 하드웨어에 따라서

그에 맞는 GC를 제공해야 된다는 것이다. 

앞으로 고급 자바 개발자가 되야되겠다...

'JAVA' 카테고리의 다른 글

자바가 확장한 객체지향  (0) 2015.06.30
자바와 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
자바 메모리 구조 >>> 2  (0) 2015.06.30
자바 메모리 구조>>1  (0) 2015.06.30
Posted by slender ankles
,