2012년 6월 21일 목요일

잘못 알려지거나 무용지물이 된 Java 상식들


잘못 알려지거나 무용지물이 된 Java 상식들


Java에 대해 잘못 알려지거나 java 5.0 이전의 정보로 현재의 java에서는 무용지물인 상식들이 몇가지 있는데 그런 종류의 상식에 대해 올바른 답을 전달하는 글이 있어 정리합니다.
원문은 http://java.dzone.com/articles/incorrect-core-java-interview(새 창으로 열기) 입니다.
 
Java의 인자 전달 방식은?
이 질문은 자바 태생과 함께해온 오랜 질문 중의 하나로 제 과거 포스팅 '자바는 call by value? call by reference?(새 창으로 열기)' 에서도 언급했던 내용입니다. 하나의 기능에서 또다른 기능, 혹은 subroutine으로 인자를 전달하는 방식은 pass by value와 pass by reference 두 가지 방식이 존재합니다만 java 세상에서는 pass by value 만이 존재할 뿐입니다. reference의 값(reference by value)을 전달할 순 있지만 reference 자체를 전달할 순 없습니다. java reference는 Call By Sharing(새 창으로 열기) 으로 설명되기도 하지만 일반적으로 쓰이는 용어는 아닙니다.

Garbage collection이란 무엇이며 어떻게 동작하는가?

일반적으로 알려진 바로는 '어떤 변수에도 할당되지 않은 Object를 가비지콜렉터가 메모리에서 정리한다' 이죠. 맞는말이긴 합니다만 조금 더 정확히 기술하자면 Root context로 부터 더 이상 strong reference 되지 않은 Object가 가비지콜렉터의 대상이 됩니다. weak reference 혹은 soft reference Object가 그 대상인거죠.

또한 System.gc()는 Full GC를 수행하라고 VM에게 힌트를 주는것이지  System.gc() 호출 시점에 GC가 수행되는것은 아닙니다. ( finalize 메소드의 오버라이딩을 자제해야 하는 이유.(새 창으로 열기) )

Transient 와 Volatile 접근 제한자는 무엇인가?
알려진 내용은 다음과 같죠.
Transient 접근 제한자는 Object를 직렬화(serialize)하여 다른곳으로 전송하거나 객체를 저장할 때 Transient 제한자가 적용된 변수는 저장되지 않는다.  Volatile 접근 제한자는 해당변수를 컴파일러에게 해당 변수가 다른 프로그램에 의해 불규칙하게 변경될 여지가 있음을 알려준다.
사실은 이렇습니다. 
transient 접근제한자는 오직 feild (클래스변수)에만 적용할 수 있으며, 지역변수에는 적용할 수 없습니다. static 변수에도 적용할수는 있지만 그 기능은 무시됩니다. trensient가 적용된 변수는 serialized 되진 않지만 writeObject(), readObject() 같은 커스텀 serialization을 통해 직렬화 할 수 있습니다.
volatile 접근 제한자 역시 feild에만 적용할 수 있으며, compiler가 아닌 JIT 쪽에 필드값을 참조할 때 메인 메모리상의 필드값이 캐시(CPU의 L1,L2캐시)에 복사하도록(캐시를 갱신) 명시하는 역할을 합니다. 멀티쓰레드 환경에서 서로 다른 쓰레드들이 갱신되지 않은 캐시로 프로그램이 오작동 할 수 있는 부분에 적용할 수 있습니다.

Integer 클래스와 int 의 차이점은 무엇인가?
Integer는 java.lang 패키지에 정의된 클래스이며 int는 Java 언어 자체에 정의되어 있는 primitive 데이타 타입이다.
딱히 틀린말은 아니지만 조금 더 정확히 표현하면 Integer는 int를 싸는(wrap) 참조 객체(reference to an object) 이고 autoboxing, unboxing이 도입된 이후의 Integer와 int의 가장 큰 차이점은 Integer는 null일 수 있는것과 == 연산자에서 Integer는 reference를 비교하거나 warpping된 값(int) 를 비교하는것 입니다. 아래 코드를 보시죠

Integer i1 = 1;
Integer i2 = 1;
// autoboxing이 적용되어 int값 비교로 true 출력.
System.out.println(i1 == i2); 
Integer i3 = 3000; Integer i4 = 3000; // autoboxing이 적용되지 않고 reference 비교를 하기때문에 false 출력. System.out.println(i3 == i4);

신기합니다. 두 Integer 객체 비교에 어떤 경우엔 true가, 또 어떤 경우엔 false가 됩니다.
이 문제의 비밀은 java실행 옵션에 있는데요. SUN/Oracle JVM의 경우 integer값을 캐시하는 기본 최대값은 127입니다. 즉 127이내의 Integer를 비교하면 autoboxing이 적용된 int를 비교하게됩니다. 물론 이 옵션은
 -XX:AutoBoxCacheMax= or -Djava.lang.Integer.IntegerCache.high=2000
과 같은 방법으로 변경할 수 있습니다.

Thread의 상태는?
Thread는 ready, running, dead 의 상태를 갖는다고 일반적으로 알려져 있습니다만 java 5.0으로 넘어오면서Thread.State(새 창으로 열기) enum이 추가되면서 
NEW : 쓰레드가 시작되지 않은 상태
RUNNABLE : JVM에서 쓰레드가 동작중인 상태
BLOCKED : block되어 monitor lock을 기다리는 상태
WAITING : 다른쓰레드가 특정한 행위를 수행할때까지 기약없이 대기하는 상태. 
TIMED_WAITING : 다른쓰레드가 특정한 행위를 수행할때까지 약속된 시간까지 대기하는 상태.
TERMINATED : 쓰레드가 종료된 상태.
의 6가지 상태로 구분됩니다.

모든 클래스의 base 클래스는?
java.lang.Object
아마 모든 Java 입문서에 나와있는 내용일겁니다. 물론 일반적인 자바객체는 java.lang.Object를 상속하고 있습니다.
하지만 이는 custom class에만 적용되는 이야기입니다. int.class, void.class와 같은 primitive 타입과 Object 그 자체는 super class가 없습니다.

Class parent = boolean.class.getSuperclass(); // returns null


Java Beans란?java beans는 '다양한 환경에서 재사용이 가능하도록 디자인된 소프트웨어 컴포넌트이다.' 라고 설명 되기도 합니다. 하지만 Java Beans(새 창으로 열기)를 좀 더 구체적으로 설명하자면 '직렬화 가능하고(serializable) 인자없는 생성자를 가지며, getter ,setter 메소드를 통하여 프로퍼티에 접근 가능한 Java Object이다.'정도가 될것입니다.

synchronized block vs. synchronized method.
일반적으로 synchronized block이  synchronized method보다 lock을 거는 주기가 더 짧다고 알려져있습니다. 옳은 말이긴하지만 항상 그렇게 동작한다고 보증할 순 없는데요. 아래는 일반적으로 사용되고 있는 코드 예시로 synchronized block에 lock으로 this가 아닌 다른 object를 사용하고 있습니다. 이런 경우 synchronized block은 synchronized method로 lock을 걸게 됩니다. 결국 synchronized block으로 lock 영역을 줄인 의미가 없어지게 되는거죠.

Map<Key, Value> map = Collections.synchronizedMap(new LinkedHashMap<Key, Value>());
// perform multiple operations in a thread safe manner
synchronized(map) {
    Value value = map.get(key);
    if (value == null)
        map.put(key, value = new Value(key));
    return value;
}

출처 : http://www.yunsobi.com/blog/572

댓글 없음:

댓글 쓰기