반응형

Class 파일은 실행 시 Link를 할 수 있도록 Symbolic Reference 만을 가지고 있다.

Runtime 시점에 실제 물리적인 주소로 대체되는 작업인 Dynamic Linking이 일어나게 된다.



Class-File-Format은 Network-Byte-Order 를 사용하기 때문에 Big-Endian 방식을 사용하게 된다.


메모리 주소값을 할당하는 방식을 Network-Byte-Order 를 사용하는데 Big-Endian을 사용하기로 약속되어있고, 서로 다른 계열의 CPU끼리 데이터를 전송받을 때의 문제점을 해결하기 위해 정해진 일종의 약속이다.


  • Gabage-Collector
    • Gabage-Collection을 통해 Heap이나 Method-Area의 사용되지 않는 Object를 Memory에서 삭제한다.
    • HotspotJVM은 Heap을 Young-Generation과 Old-Generation으로 나누어 사용한다.
    • Young-Generation은 Eden영역과 Survivor영역이 존재한다. 객체가 Eden영역으로 처음 Allocation 되며 자주 사용되던 객체가 Old영역으로 가기 전에 Survivor 영역으로 이동하게 된다.
    • Old-Generation은 성숙된 객체들이 Promotion 되는 장소이다.
    • Minor-GC는 Young-Generation에서 발생, Promotion이 발생...
    • Major-GC는 Old-Generation에서 발생, Minor-GC를 통해서 발생할 수도 있음...
    • Full-GC는 너무많은 클래스 로딩으로 Permanent-Area가 부족하게 되어 발생할 수 있음...
    • 잘못하면 suspend-time이 길어져 Stop-The-World 방식의 Compaction으로 회귀할 수 밖에 없음.
  • Gabage-First-Collector
    • Generation 구분을 없애고 Region 으로 재편하였다. 논리적인 구분?
    • 물리적인 Young/Old 영역에서의 Allocation/Promotion 대신 Gabage로만 꽉 차 있는 Region부터 Collection을 시작한다고해서 붙여진 이름이다.
    • G1 Collector는 철저하게 Region 단위로 Gabaga-Collection 이 발생한다. 따라서 Suspend 현상도 Region을 사용하는 Thread에 국한된다.
  • Calss-Loader
    • JVM 안으로 Class를 Load 하고 Link를 통해 적절히 배치하는 일련의 작업을 수행하는 모듈.
    • *.class 파일들을 Runtime-Data-Area 에 적재한다.
    • Bootstrap-Class-Loader(jre/lib/rt.jar), Extention-Class-Loader(jre/lib/ext), Application-Class-Loader(System-Class-Loader, User-Defined-Class-Loader)
    • java5부터 Class-Sharing 제공...
    • Load-Time-Dynamic-Loading과 Runtime-Dynamic-Loading 이 있다...
    • Class-Loader-Work 는 Loading, Linking, Initialization의 세가지 과정이 있다. 클래스파일이 검증을 거쳐 symbolic-reference 가 direct-reference 로 변경되는 과정이다.
  • Executor-Engine
    • Load된 Class의 Bytecode를 실행하는 Runtime-Module이다.
    • 모든 ByteCodes를 Interpreter 방식으로 처리하여 초기의 JVM은 실행속도에 있어서 약점을 가지고 있었는데,  JIT(Just-In-Time) Compiler 방식이 등장하여 문제점을 보완하였다.
    • JIT(Just-In-Time) Compiler 는 Bytecodes 를 NativeCode로 Compile하여 실행시간을 빠르게 하였다. 보통 두 방식을 섞어서 쓴다(Lazy Fashion).
    • loop 와 다차원배열 처리에 성능적으로 약함...


  • Runtime-Data-Area
    • Process로서의 JVM을 수행하기 위해 OS로부터 할당받는 메모리 영역.
    • PC Register, Java Virtual Machine Stacks, Method Area, Heap, Native Method Stacks.
    • PC Register
      • 각 Thread마다 하나씩 존재하며 Thread가 시작할 때 생성된다. Stack-Base로 작동하며 현재 수행중인 JVM 명령어를 가지게 된다.
    • Java Virtual Machine Stacks
      • 각 Thread마다 하나씩 존재하며 Thread가 시작할 때 생성된다. 여러 Stack-Frame들이 있고 현재 수행하고 있는 Method의 정보를 저장하는 것을 Current-Frame 이라고 한다.
      • Stack-Frame은 Local-Variable-Section, Operand-Stack, Frame-Data 세 부분으로 되어 있다.
    • Native Method Stacks
      • 각 Thread마다 하나씩 존재하며 Thread가 시작할 때 생성된다. Native-Code로 호출한 메소드에 대한 Stack 영역.
    • Method Area
      • 모든 Thread들이 공유하는 메모리 영역이다.  JVM이 기동할 때 생성이 되며, Garbage-Collection의 대상이 된다. ClassLoader에게 넘겨받은 ClassFile에서 Type 관련 정보를 추출하여 저장하게 된다. Type-Information, Constant-Pool, Field-Information, Method-Information, Class-Variable, ReferenceToClass-ClassLoader, ReferenceToClass-Class, Method-Table.
    • Heap
      • 모든 Thread들에 의해 공유된다. 메모리 해제는 Gabage-Collection을 통해서 이루어지고, Instance(Object)와 Array객체 두 가지 종류만 저장되는 공간일 뿐이다. 실제 구현에 대해서는 각 벤더에게 위임하였다. HotspotJVM이나 IBM-JVM의 Object-Layout과 Heap 구조를 통해 JVM의 Heap에 대한 전반적인 이해를 하는 것이 의미있을 것이다.

Class와 Instance의 관계

Java 관련 서적을 보면 Class와 Instance를 붕어빵틀과 붕어빵으로 표현하는데, 이것은 좋은 비유라고 생각한다. Class가 Loading 되면 Method-Area 에는 Java로 작성한 Code에서 Class의 속성들을 추철하여 정보화되어 기록된다. 다시 말해 하나의 틀이 만들어지는 셈이다. 이를 테면 이 Class는 이러이러한 Method가 있고 이 내용은 어떠하여 변수는 어떤 것을 가진다는 정보가 MethodArea에서 생성된다.

 만약 누군가가 이 Class에 대한 Instance를 하나 생성하려고 한다면 Method Area의 Class 정보를 틀로 하여 Heap에 Object를 하나 찍어낸다. 이것이 Instance이고 여기에 실제 변수에 대한 실제 메모리 상의 주소 등을 포함하여 사용하게 되는 것이다.

 Member Variable(Instance Variable)의 경우는 Heap에 생성된 Instance에 그 값이 저장되고 Class Variable은 이 Class 정보가 있는 Method Area, 더 정확하게는 Class Variable에 저장된다.


  • Thread...
    • Native Thread 를 White-Thread로 부르고, JVM의 Thread를 Green-Thread라고 부르던 때가 있었다...(JAVA 1.1)
    • JAVA1.2부터 ... 둘이 혼용된 Thread-Model ...
    • JAVA1.3부터 결국엔 Native 가 Default-Thread-Model...
    • GreenThread는 MultiProcessSystem에서 이점을 가질 수 없었다...

Synchronization이 필요한 지역을 Critical-Section이라 하고, Thread가 Critical-Section에 들어가면 반드시 Synchronization 작업을 수행하게 된다. 바꾸어 말하면 Thread 가 Critical-Section에 들어가기 위해서는 Lock을 요청하는 것이고 이 Critical-Section은 Synchronization으로 보호되고 있다고 할 수 있다.


- Object Header에 lock-counter를 통해서 알 수 있다...





반응형
반응형
  • JAVA1
    • Collection이 없어서 Vector, Stack, Hashtable, Properties 가 컬렉션의 명명법을 따르지 않음.
    • Vector, HashTable 클래스들은 동기화처리됨.

  • JAVA1.1
    • Reflection
    • Calendar 

  • JAVA1.2
    • Collection 프레임워크 등장
    • ArrayList, HashMap 클래스들은 동기화처리하지 않고 필요한 경우에만 java.util.Collections 클래스의 동기화 메소드를 이용.

  • JAVA1.3
    • Hotspot-Compiler 내장...(불필요한 컴파일을 회피하고 HotCode에 Optimization을 집중..)
    • Math 의 OS 의존성 때문에 (CPU명령어처리가 다르니까..) StrictMath 가 탄생했다.

  • JAVA1.4
    • CharSequence 가 추가되어 String, StringBuffer 등의 클래스가 구현하였다.

  • JAVA1.5
    • enhanced for-looop
    • Generics 가 추가됨.
    • Iterable 인터페이스 추가.(Collection 인터페이스가 상속받도록 결정)
    • enum(열거형)이 추가됨.
    • Autoboxing 이 추가됨. 기본형과 참조형 사이의 연산이 가능해짐. 
    • Covariant ReturnType(공변반환타입)이 추가되어 Override하는 함수의 반환타입을 SubClass 타입으로 쓸 수 있게 함.
    • 메소드의 매개변수에 동적으로 할당 할 수 있게 가변인자(variable arguments)가 추가되었음.
      • 가변인자는 매개변수 중 제일 마직막에 선언, 내부적으로 배열을 생성하므로 성능을 고민해야 함
    • java.util.concurrent.locks 와 java.util.concurrent.atomic 패키지 추가.
    • String의 contains(CharSequence s), replace(CharSequence old, CharSequence nw)가 추가되었다.
  • JAVA1.6
    • 상수를 선언과 동시에 초기화하지 않아도 되며, 사용하기 전에만 초기화하면 되도록 바뀌었다.

  • JAVA1.7
    • 정수형 리터럴 중간에 '_' under-score를 넣을 수 있게 되었다.
    • 2진 리터럴이 추가되었다. 
    • switch 문 조건식에 문자열이 추가되었다
    • '|' 기호를 이용한 multi-catch 블럭.
    • try-with-resources 가 추가되었음.
      • 보통 입출력관련 클래스들을 사용할 때 close()를 호출하지 않아도 try 블럭을 벗어나는 순간 자동적으로 호출이 된다.
      • AutoClosable 인터페이스를 구현한 클래스여야만 한다.
    • Generics 객체 생성 시 추정가능한 경우 타입을 생략할 수 있다.
      • List<String> list = new ArrayList<>();
    • @SafeVarargs Generics 가변인자에 사용.
    • fork & join 프레임워크가 추가됨.
    • '+'가 포함된 문자열이 parseInt()로 변환가능하게 된 것은 JDK1.7부터이다.

  • JAVA1.8
    • 람다와 스트림.
    • 인터페이스에 default-method와 static-method 가 추가되었다.
    • (지역클래스에서 접근하는 지역변수...)Inner-Class에서 외부클래스의 지역변수는 final을 붙여야 했으나, JAVA8부터 final을 생략할 수 있게 바뀌었다.(대신 컴파일러가 자동으로 붙여준다.)
    • java.time 패키지로 개선된 날짜/시간 제공.
    • java.util.Object 의 hash() 함수의 추가로 Override한 hashCode 구현 지원.
    • @FunctionalInterface 함수형인터페이스 선언.
    • @Native native 메소드에서 참조되는 상수 앞에 붙인다.
    • @Repeatable 어노테이션을 반복해서 적용할 수 있게 한다.

  • ETC
    • JVM이 모든 배열의 길이를 별도로 관리하며 arrayName.length ...
    • array vs arrayList
    • Comparable은 기본적으로 오름차순이기 때문에, Comparator를 구현하여 정렬기준을 바꿀 수 있다.
    • Generics 는 컴파일 시 형변환되어 *.class 파일에는 없는데 주된 이유는 이전 버전 호환을 위해서이다.


반응형
반응형

OIO(Old Input/Output) 와 NIO(Non-blocking Input/Output or New Input/Output) 


 몇 년 사이 두드러진 netty(http://netty.io/) 나 vert.x(http://vertx.io/) 등과 같은 네트워크 라이브러리를 잘 활용하기 위해서는 비동기에 대한 못지 않게 OIO(Old Input Output) 과 NIO(Non-blocking Input Output or New Input Output) 에 대한 개념에 대해 알고 있어야 합니다.


 Java 에서 NIO 는 JDK1.4 에서부터 지원을 하기 시작했는데요. 기존의 Java I/O 는 socket 을 accept() 할 때와, data 를 read() 할 때 해당 Thread 가 Block 이 되는데요. 이런 구조? 때문에 Multi-Thread 를 사용하게 되었으나, 컴퓨터가 처리할 수 없을 정도의 요청이 들어오게 되면 Stack 에 메모리를 할당해야 하는데, 운영체제에 따라 다르지만 보통 64KB 에서 1MB 까지 차지할 수 있다고 합니다. Java는 JVM 을 통해서 많은 수를 처리할 수 있다고 하지만 그럴 경우에는 Context-Switching 에 따른 OverHead 가 크다고 합니다.


Java IO: A classic IO server design - one connection handled by one thread.



 하여튼 Multi-Thread 만으로는 부족하여, polling 과 thread-pool 을 같이 사용하기도 하지만 이또한 완벽한 비동기를 구현하기는 어렵습니다. 그래서 JDK1.4에서는 Non-blocking I/O lib 를 통해서 운영체제 레벨에서 지원되던 것을 Java를 통해서 사용할 수 있도록 했습니다.


Java NIO: A single thread managing multiple connections.


 Java NIO 에 대한 사용을 간단하게 설명하면, Selector 를 생성하여 ServerSocketChannel 에 등록하고 대기상태 없이 Selector의 SelectedSet 에서 ServerSocketChannel 로 들어온 이벤트와 관련된 SelectionKeySet 을 잃어와 이로부터 channel을 구하여 데이터를 처리하게 됩니다. 이 과정에서 Selector 는 Multi-channel 의 작업을 Single-thread 에서 처리할 수 있도록 되어 있는데 이 동작을 Multiplexing 이라 할 수 있습니다. Thread 를 사용하지 않으면서 Thread를 사용하는 효과를 볼 수 있습니다.


Java NIO: Reading data from a channel until all needed datas is in buffer.



 이를 통해, 다수의 클라이언트를 하나 또는 적은 수의 Thread로 처리하게 됨으로써, 메모리 관리와 Context-Switching에 따른 Overhead 가 감소하게 됩니다. 입출력을 처리하지 않을 때는 Thread 를 다른 작업에 활용할 수도 있습니다.




ref) http://tutorials.jenkov.com/java-nio/index.html

ref) http://javacan.tistory.com/entry/87

ref) https://devlearnings.wordpress.com/2010/09/21/tip-use-scheduledexecutor-instead-of-thread-for-polling-or-infinite-loops/

ref) http://www.ibm.com/support/knowledgecenter/SSCRJU_4.0.0/com.ibm.streams.dev.doc/doc/pollingsource.html


반응형
반응형


Interface


 자바에서 간단했던 인터페이스가 JAVA8 의 등장으로 추가된 내용들이 생겼습니다. 항상 쉽게 생각할 수 있지만, 이런 것들이 막상 설명하려면 어렵게 느껴질 때가 있는데요.


 기존의 인터페이스를 간단히 요약하면 다음과 같습니다.


모든 멤버변수는 public static final 이어야 하며 이를 생략할 수 있으며,

모든 메소드는 public abstract 이어야하고 이를 생략 수 있습니다.


이처럼 간단하게만 알고 있었으며 사용하고 있었는데요. 조금 더 자세하게 이야기 해 보도록 하겠습니다.


 자바에서의 인터페이스는 클래스의 bluprint 입니다. 인터페이스는 앞서 이야기 했듯이 static constants 와 abstract methods 로만 이루어져 있습니다. 자바에서의 인터페이스는 완전한 추상화를 만들기 위한 메커니즘입니다. 메소드의 몸체가 없는 자바의 인터페이스는 추상메소드로만 되어 있습니다. 이것이 완전한 추상화를 달성할 수 있게하며 자바에서 다중상속이 이루어지도록 합니다.


 자바의 인터페이스는 또한 IS-A 관계를 표현합니다. 인터페이스는 추상클래스처럼 초기화 될 수 없습니다.


왜 자바의 인터페이스를 사용할까요?


인터페이스를 사용하는 주요한 4가지 이유가 있습니다.

  • 완벽한 추상화를 달성하기 위함입니다.
  • 인터페이스를 사용함으로써, 다중상속의 기능을 지원할 수 있습니다.
  • 인터페이스의 사용은 약한 결합을 이룰 수 있게 합니다.
  • 다형성을 사용할 수 있습니다.

자바 컴파일러는 인터페이스의 메소드 앞에 public 과 abstract 키워드들을 붙이고 멤버변수 앞에 public, static, final 키워드들을 붙입니다.


다른말로, 자연스럽게 인터페이스의 필드들은 public, static 그리고 final 이며 메소드들은 public absctract 입니다.




클래스와 인터페이스 사이의 관계 이해하기.


 아래의 이미지에서 보는 것과 같이, 클래스는 다른 클래스를 extends 하고 인터페이스는 다른 인터페이스를 extends 하지만 클래스는 인터페이스를 implements 합니다.



자바의 인터페이스에 대한 간단한 예제


이 간단한 예제는, 오직 하나의 메소드만을 가지는 Printable 인터페이스이고, 이 구현은 A4 클래스에서 제공되어 집니다.


package com.joochang.test3;


interface Printable {

    void print();

}


public class A4 implements Printable {


    @Override

    public void print() {

        System.out.println("Hello");

    }

    public static void main(String[] args) {

        A4 a4 = new A4();

       a4.print();

    }

} 



인터페이스에 의한 자바에서의 다중 상속.


 만약 한 클래스가 여러 인터페이스들을 implements 한다면, 또는 한 인터페이스가 여러 인터페이스들을 extends 한다면 알려진 것과 같이 다중상속 입니다.



package com.joochang.test3;


interface Printable {

    void print();  

}  

  

interface Showable {

    void show();  

} 


public class A8 implements Printable, Showable {

    public void print() {

        System.out.println("Hello");

    }

    public void show() {

        System.out.println("Welcome");

    }

    public static void main(String args[]){

        A8 obj = new A8();  

        obj.print();

        obj.show();

    }

} 



질문) 다중 상속은 자바에서 클래스를 통해 지원되지 않으나 인터페이스는 가능하다, 왜 그런가?

 여기서 인터페이스를 설명했던 것처럼, 다중상속은 클래스의 경우에 지원되지 않습니다. 그러나 인터페이스는 지원되는데 왜냐하면 구현 클래스에 의한 구현을 할 때 애매모호함이 없습니다.


package com.joochang.test3;


interface MultiInheritance1 {

    void print();  

}  

  

interface MultiInheritance2 {

    void print();  

} 



public class MultiPleInheritance1 implements MultiInheritance1, MultiInheritance2 {


    @Override

    public void print() {

        System.out.println("Hello World!");

    }

    public static void main(String[] args) {

        MultiPleInheritance1 test = new MultiPleInheritance1();

        test.print();

    }

} 


 위에 있는 예제처럼, MultiInheritance1 과 MultiInheritance2 인터페이스는 같은 메소드를 가지고 있지만 그 구현은 MultiPleInheritance1 클래스에 의해서 제공되어 지는데, 그래서 이러한 점에 애매모호함이 없습니다.



인터페이스 상속


클래스는 인터페이스를 implements 하지만 인터페이스는 다른 인터페이스를 extends 합니다.


package com.joochang.test3;


interface MultiInheritance3 {

    void print();  

}  

 

interface MultiInheritance4 extends MultiInheritance3 {

    void show();  

}


public class MultiPleInheritance2 implements MultiInheritance4 {


    @Override

    public void print() {

        System.out.println("Hello World 1 !");

    }

    @Override

    public void show() {

        System.out.println("Hello World 2 !");

    }

    public static void main(String[] args) {

        MultiPleInheritance2 test = new MultiPleInheritance2();

        test.print();

        test.show();

    }

} 


질문) marker 또는 tagged 인터페이스는 무엇인가?


 어떠한 멤버도 없는 인터페이스가 marker 또는 tagged 인터페이스라고 알려져 있습니다. 예를 들면, Serializable, Cloneable, Remote etc. 이것들은 JVM 에게 몇가지 특별한 정보를 제공하기 위해서 사용되어 지는데 그래서 JVM 이 유용한 동작을 수행할 것 입니다.


//How Serializable interface is written?

public interface Serializable{



자바에서의 중첩 인터페이스


Note : 중첩 인터페이스라고 알려진 것과 같이, 인터페이스는 다른 인터페이스를 가질 수 있습니다. 


interface printable{

    void print();

    interface MessagePrintable{

        void msg();

   }



since jdk 1.8  default method in java interface ... 


since jdk 1.8  static method in java interface ...



참고) http://www.javatpoint.com/interface-in-java




반응형
반응형

 Covariant return type 우리 말로 '공변 반환 타입' 이라고 하는데, 리턴 타입은 서브클래스라는 범위 안에서 다양할 수 있다는 것으로 java 1.5 부터 적용 되었습니다. 본래 오버라이딩이 이름이 같아야하고, 매개변수가  같아야 하며, 반환타입 또한 같아야 하는데 java 1.5 부터 Primitive 타입이 아닌 Subclass 타입으로 오버라이딩이 가능하게 된 것 입니다.



refer ) http://www.javatpoint.com/covariant-return-type

          http://www.java-tips.org/covariant-return-types.html


반응형
반응형


예전 블로그 복사 - http://blog.daum.net/7dbwnckd/4696550


GC(Garbage Colloection)는 언제 발생할까?

1. GC의 원리

 - 메로리 할당

 - 사용 중인 메모리 인식

 - 사용하지 않는 메모리 인식

 

 - JVM의 메모리는 크게 클래스 영역, 자바 스택, 힙, 네이티브 메소드 스택 4개 영역으로 나뉘지만, 가비지 컬렉터가 인식하고 할당하는 자바의 메모리 역역에 대해 공부하자!!(힙)

  Young, Old, Perm(permanent)의 세 영역으로 나누어지는데,

  Young 영역은 Eden, Survivor1, Survivor2

  Old 영역은 메모리영역

 * 일단 메모리에 객체가 생성되면, Eden영역에 객체가 지정된다. Eden영역에 데이터가 어느 정도 쌓이면, 이영역에 있던 객체가 어디론가 옮겨지거나 삭제된다. 이 때 옮겨지는 위치가 Survivor영역이다. 우선순위는 없으며 두 개의 영역 중 한 영역은 반드시 비어 있어야 한다. 그 비어 있는 영역에 Eden 영역에 있던 객체가 할당된다. 할당된 Survivor 영역이 차면, GC가 되면서 Eden 영역에 있는 객체와 꽉 찬 Survivor 영역에 있는 객체가 비어 있는 Survivor 영역으로 이동한다. 그러다가 더 큰 객체가 생성되거나, 더 이상 Young 영역에 공간이 남지 않으면 객체들은 Old 영역으로 이도하게 된다.

 

2. GC의 종류

 - 마이너 GC : Young 영역에서 발생하는 GC

 - 메이저 GC : Old 영역이나 Perm 영역에서 발생하는 GC

 이 두 가지 GC가 어떻게 상호 작용하느냐에 따라서 GC 방식에 차이가 나고, 성능에도 영향을 준다. GC가 발생하거나 객체가 각 영역에서 다른 영역으로 이동할 때 애플리케이션의 병목이 발생하면서 성능에 영향을 주게 된다. 그래서 핫 스팟(Hot Spot) JVM에서는 스레드 로컬 할당 버퍼(TLABs: Thread-Local Allocation Buffers)라는 것을 사용한다  이를 통하여 각 스레드별 메모리 버퍼를 사용하면 다른 스레드에 영향을 주지 않는 메모리 할당 작업이 가능해진다.

 

 

반응형

+ Recent posts