Java9 에서 새로 추가된 JShell 을 이용하면 마치 Java를 파이썬을 사용하듯이 손쉽게 프로토타이핑할 수 있다.


JShell 이란 Command Line Interface 로 제공되는 자바 코드 작성을 위한 도구이다.


당연히 복잡한 종류의 모듈을 JShell 을 이용해 제작하는 건 무리지만, 간단히 자바 코드를 실행하고, 모듈을 작성해보거나, 


Java Library 의 기능을 테스트해보아야 한다면 실무에서도 유용한 도구이다.



JShell 을 이용하는 방법은 다음과 같다.


1. Java9 를 설치한다.



2. 환경변수 Path 에 설치된 경로를 지정한다.




3. 커맨드 라인에서 Jshell 을 실행한다.




Jshell 을 이용하면, 커맨드라인에서 즉시 자바 명령어를 실행할 수 있으며, 다음과 같이 모듈의 Import 및 사용 역시 가능하다.


이렇게 실행하는 Java Statements, Definition, Expression 등을 스니펫(Snippet) 이라고 하며, 스니펫을 실행하면 JShell 에서 즉각적인 피드백(Feedback)을 제공해준다.






또한 JShell 은 위의 그림에 마지막에 작성된 스니펫인 /edit 을 이용하면, 별도의 Edit pad 를 제공하는데, 


이를 이용하면 JShell 만을 이용해서도 마치 IDE 를 사용하는 듯 하게 에디터를 이용해 작업을 해볼 수 있다.





실행시킨 Jshell 은 /exit 명령어를 이용해서 종료할 수도 있다.


실무에서도 JShell 은 간단한 코드를 프로젝트 수정없이 테스트할 경우 굉장히 유용하며, 본인은 때때로 알고리즘을 테스트할 때 JShell 을 이용하기도 한다.


따라서... 이제는 더 이상 간단한 자바 코드의 Prototyping 을 위해 이클립스를 켜지 않아도 된다!


이처럼 Java 는 버전을 올려감에 따라서 함수형 언어의 특징을 받아들이면서 좀 더 Modern 한 언어의 특징을 위해 업그레이드되어 가고 있다.


좀 더 자세한 사용은 아래 블로그에 잘 정리되어있으니 참고해보는 것도 좋을 듯 하다.


http://taewan.kim/post/trans_jshell/



자바의 클래스로더는 자바의  Class  들을 런타임에 JVM으로 로딩하는 역할을 한다.
클래스로더는 JRE(Java Runtime Environment)의 한 부분이다.


JVM은 클래스로더 덕분에 파일의 구조나 파일 시스템을 고려하지 않을 수 있으면서 자바 프로그램을 작동시킬 수 있다.

이는 C/C++언어의 결과처럼 자바 프로그램이 하나의 Single Executable 파일을 생성하는 것이 아니라 여러 개의 자바 클래스들이 JAR의 형태로 묶여서 관리되다가 JVM에 의해 메모리에 올라가서 바이너리 형태로 동작하기 때문에 생기는 차이점이라 할 수 있다.

자바 클래스들은 한번에 모든 클래스가 메모리에 올라가지 않는다. 각 클래스들은 필요할 때 어플리케이션에 올라가게 되며, 이 작업을 클래스로더가 해주게 된다.

 

Class Loader 는 다음과 같은 역할을 해준다. 


 - Loading : 클래스 파일에서 클래스 이름, 상속관계, 클래스의 타입(class, interface, enum) 정보, 메소드 & 생성자 & 멤버변수 정보, 상수 등에 대한 정보를 로딩해서 Binary 데이터로 변경한다.


 - Linking : Verification 과 Preparation, Resolution 단계를 거치면서 바이트코드를 검증하고 필요한 만큼의 메모리를 할당한다. Resolution 과정에서는 Symbolic Reference 를 Direct Reference 등으로 바꿔준다.


 - Initialization : static block 의 초기화 및 static 데이터들을 할당한다. Top->Bottom 방식으로 클래스들을 해석한다.


(자세한 기능 동작은 다음을 참조

https://jins-dev.tistory.com/entry/JVMJava-Virtual-Machine-%EC%9D%B4-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94-%EC%A7%80-How-JVM-Works)


자바의 클래스로더는 3가지의 서로다른 클래스로더로 구성되어 있다.

 

 (1) Bootstrap Class Loader
가령 java.lang 이나 ArrayList 같이 java.lang.ClassLoader 가 로드할 수 없는 bootstrap 또는 primordial 클래스들에 대해서는 JRE의 Bootstrap ClassLoader 가 이 역할을 해준다.
Bootstrap ClassLoader 는 native 언어로 만들어진 JVM 코어의 일부분으로, 일반 클래스 로더가 불러올 수 없는 클래스 들의 로딩을 담당해준다.

 

 (2) Extension Class Loader
Extension Class Loader는 bootstrap Class loader 의 자식클래스로 일반적인 Core Java Class 들의 로딩을 담당한다.

 

 (3) System Class Loader
System Class Loader는 시스템 환경변수 또는 클래스 변수 등과 같은 환경에 종속된 클래스들에 대한 로딩을 담당한다.


클래스로더는 런타임에 모든 클래스들에 대한 정의를 로딩한다. 이때 만약 클래스 매핑에 실패한다면, NoClassDefFoundError 를 만나보게 된다.

 

Java 의 클래스로더는 3가지 원칙을 지키며 동작한다.

 

1. Delegation :  Java의 클래스는 필요할 때 로딩되어야 한다는 원칙이다.

 

2. Visibility : Child 클래스는 Parent 클래스로더에 의해 로딩된 클래스들을 확인할 수 있지만, 그 역은 불가능하다는 원칙이다.

 

3. Uniqueness : 한번 클래스로더에 의해 로딩된 클래스는 재로딩되지 않는다. 가령, Parent 클래스로더에 의해 이미 로딩된 클래스는 Child 클래스로더가 다시 로드하지 못한다.

 

Java의 ClassLoader 클래스를 상속하면, 사용자정의 클래스로더를 구현할 수도 있으며, 언제든 findClass() 와 loadClass() 메서드를 이용해 동적으로 로딩이 가능하다.






 Java에서는 Static 변수의 Non static 초기화를 위해 Static Initializer를 지원한다.

이는 static final 변수를 주로 예외를 throw하는 함수의 return 값으로 초기화하는데 사용된다.


다음과 같이 사용하면 된다.


(ex)



public class Example {

private static final Lib val;

static{
Lib tmp = null;
try{
tmp = new Lib();
}catch(UnknownHostException e){
//생성자가 이 예외를 반환하므로 일반적인 방법으로는 선언과 동시에 초기화가 불가능하다.
}
}

}



 이는 Lazy Initialization 의 예시로, 이러한 테크닉을 이용하면 Lazy Instantiation 과 유사하게 디자인 패턴 내의 코드를 작업하는 데 있어서 유연성을 가져올 수 있다.


 위의 예제에서 val 이라는 멤버변수는 final 인데다가 static 변수이면서 유효한 Lib 형의 객체이다. 안전하면서도 효율적이다.

위의 코드는 심지어 Thread-safe 하기 때문에 멀티 스레드 환경에서도 문제 없다.

 또한 위의 주석에 설명이 달려있듯, 생성자 자체가 예외를 발생시키는 경우 위와 같이 바깥에서 Try Catch 로 감싸줌으로써 안전한 초기화가 가능하다.


 다만, 이런 형태에서 위의 변수 val, 즉, Static Initialized Variable 은 클래스로더에 종속되기 때문에, 매번 객체 생성 시, 서로 다른 클래스 로더에서 Static 코드 블록을 호출하게 된다. 


 만약 하고자하는 바가 싱글턴이거나, 외부 코드에 종속적이라면 추천되지 않는 패턴이다. (물론 그렇게 쓰이는 경우는 흔치 않다.)



+ Recent posts