Header

  1. View current page

    chan님의 노트

Profile_img_60x60_01
0

Java VM Spec Chapter8 The Linking Model

 The Linking Model

프로그래머의 관섬에서 Java 아키텍쳐의 linking model을 이해하는것은 중요함.

이전에 말했듯이 자바 링킹 모델은 프로그램실행시 유져 디파인 클래스 로드를 디자인하는것을 허용한다.

 

유져 디파인 클래스 로더는 당신의 어플리케이션이 컴파일되었을때 알지 못했거나, 존재하지 않았던 클래스와 인터페이스를 load 하고 동적 링킹을 할 수 있다.

자바링킹은 모델 분석방법을 유도하는 엔진이다. 이전챕터는 class의 life time에 대해서 봤지만 자세히는 안 봤다. 이장에서 깊이있게 보자. 그리고 다이나믹 익스텐션에서의 분석법을 보자. 링킹 모델의 overview, 상수풀의 설명, 메소드테이블의 기술(desc), class loader을 어떻게 짜야하고, 어떻게 사용되는지 몇가지 예제등을 본다.

 

Dynamin Linking and Resolution

자바프로그램 컴파일하면 class및 interface가 class File로 나온다. 이 화일들은 독립적이며, 다른 클래스나 자바 API(rt.jar?)의 심볼릭 커넥션을 가지고 있다. 프로그램을 수행하면 JVM이 class와 interface를 load하고 다이나믹 링킹의 처리에서 그것들을 hook한다. ( 낚아 챈다. - 컨트롤 한다. )

 

마치 당신의 프로그램이 인터넷상에 있는 클래스나 인터페이스를 JVM이 build하는것 처럼 수행된다. class화일은 모든 심볼릭레퍼런스를 상수풀에 저장, 모든 class File은 상수풀을 가지고 있고 각 클래스나 인터페이스는 JVM이 가지고 있는 런타임 컨스탄트풀이라고 불리는 컨스탄트풀로 로딩된다.

(컨스탄트풀 - 클래스화일에 구조체의 구현이 정의되어 있다.  ) 이와 같이 type이 다 로드되고 나면 모든 심볼릭 레퍼런스는 런타임 컨스탄트 풀에 저장되게 된다.

 

프로그램 동작중에 각 심볼릭레퍼런스가 사용되어진다면 모두 분석되어져야만 한다. 레졸루션(분석)이란 심볼릭 레퍼런스와 심볼릭 레퍼런스를 다이나믹 레퍼런스로 연결하여 고유한 엔티티(정보단위)를 찾는 것이다. 모든 심볼릭 레퍼런스는 콘스탄트 풀안에 있기 때문이다. 이러한 과정을 constant pool resoultion 이라고도 부른다.

 


6장에 적었다 시피 컨스탄트 풀은 연속된 아이템의 집합이다. 각 아이템은 고유한 인덱스를 가지고 있고, much like an array item,

심볼릭 레퍼런스는 상수풀에서 나타날수있는 아이템의 한 종류

JVM 명령들이 심볼릭레퍼런스가 있는 constant pool에서의 각 심볼릭 레퍼런스에 지정된 index를 사용한다.

예를들면 static field값을 stack에 올리는 getstatic opcode는 constant pool의 index를 나타내는 bytecode stream뒤에 나온다.

 


CONSTANT_Fieldref_info 엔트리의 index는 필드가 존재하는 class의 fullName과 필드이름과 type를 가리킨다. JBM은 로드한 각 클래스와 인터페이스의 독립적인 runtime constant pool을 가진다.

명령이 콘스탄트풀에서 5번째 아이템을 가리키고 있다면 현재 수행중인 메소드가 정의된 클래스의 constant pool의 5번째 아이템을 가리키는 것이다.

 


똑같거나 다른 메소드이 몇몇 명령어들이 상수풀의 같은 엔트리를 참조한다면 딱한번만 resolve 된다. 한 명령에 의해서 심볼릭 레퍼런스가 해석되어지고 난 후에는, 그이후에 다른 명령에 의해서 resolve를 시도하게 되면, 이미 끝났기 때문에 hard work에 대한 이득을 취할 수 있고 원래의 레졸류션으로부터 같은  다이렉트 레퍼런스의 결과를 이요할 수 있다.


링킹 involve 는 심볼릭 레퍼런스를 direct 레퍼런스로 바꾸어주기도 하고, 이상없음과 권한 체크도 한다. 7장에서 언급했듯이 심볼릭 링크의 존재여부와 퍼미션체크는 레졸루션에서 수행한다. 예를 들어 JVM이 다른 클래스에 있는 field의 getstatic명령으로 수행하려고 한다면 체크한다. 

A4에 정리 약간


7장에적었듯이 JBM의 구현이 다를때에는 서로 다른 시간(지점)에서 레졸루션을 수핸한다. 초기클래스의 모든 심볼릭 레퍼런스가 resolve 될때까지 초기클래스로부터 모든 심볼릭레퍼런스를따라서 link everything up으로 구현가능한 방법도 있다. main()이 수행되기 전에 모든 reference들이 완전히 link 된 상태이고 이를 early resolution이라고 부른다.

반대로 마지막까지 심몰릭 레퍼런스의 resolution을 기다리는 방법이 있는데 JVM이 프로그램을 수행하다가 처름 만나는 경우에만 수행하고 이를 late resoltion이라고 부른다. 물론 두개를 섞어서 사용할 수도 있다.


비록 JVM의 구현이 언제 심볼릭 레퍼런스를 resolve할지 자유롭게 선택할 수 있기는 하지만 모든 JVM이 late resoltion을 사용하도록 외압을 준다. (?)

 


각 JVM이 레졸류션을 수행하는것은 문제가 않는다. 프로그램이 수행될때 심볼릭 레퍼런스가 최초로 실제 사용되어지는 곳에서 심볼릭 레퍼런스를 resolve 결과를 뱉을때 항상 어떠한 에러가 발생될것이다. 이 방법은 유져에게 레졸루션이 늦었다고 나타내 줄것이다. ( late resoltion을 사용했다는 의미인것 같음 )


만약 JVM이 early레졸루션을 쓰고 ralry레졸루션하는 도중에 class file missing( 클래스 화일을 찾을 수 없음 ) 이 발생했다면, 프로그램의 어떤 클래스에서 심볼릭 레퍼런스를 실제로 사용할때까지 클래스 화일이 없다고 에러를 report 하지 않는다. 클래스 화일이 프로그램에서 사용되어지지 않는다면 에러가 발생하지 않을꺼다.  ( 아마도 early를 사용해도 사용되지 않는다면 class 를 check하지 못한다는 의미로 보임 )


Resolution & Dynamin Extenstion

런타임에 simple linking type은 Java Application은 런타임에 링크할 type를 결정한다.  자바 아키텍쳐는 자바프로그램들이 런타임에 다른 type를 사용하는것, 로딩하는것, 사용하는것을 결정하는 방법인 dynamically extend를 허용한다. Class class 의 forName()이나, ClassLoader를 상속받아 직접 구현한 자식클래스로더의 객체의 loadClass()의 인자로 name을 넘겨서 다이나믹 익스텐드를 할 수 있다. 당신 프고그램의 소스코드에 없는 type를 프로그램 실행도중에 이름만을 가지고 로딩가능하게 해 준다. ( 대충 무슨 뜻인지 알아 먹겠지? ㅋㅋ )

 

예를 들어 자바가 동작가능한 웹브라우져에서는 네트워크넘어에 있는 애플릿을 위한 클래스화일을 로드한다. 브라우져가 시작될때 네트워크너머의 어떤 클래스 화일이 로드되어야 할지 모른다. 웹페이지에 포함되어 있는 각 애플릿의 클래스 이름과 인터페이스 명을 브라우져가 알 수 있다.  ( 그렇게 해서 invokie 하는것인가 보다. .... )

 

잡설은 치우고 Java App에서 forName()메소드를 쓰는 다이나믹 익스텐드를 보자. String는 fullName이 들어가야 하고 boolean이 true이면 forName()이 반환되기 전에 link와 초기화를 수행한다. false이면 load와 link만 하고 초기화는 하지 않는다. 그럼에도 불구하고 type이 이전에 forName()명령에 의해서 이미 초기화 되었다면 아무리 니가 false로 넘겨주어도 초기화된 type가 반환될것이ㅏㄷ.

 

세번째 파라미터인 classloader는 이나 만듬 클래스로드로부터 forName()을 하고 싶다면 파리미터로 넘겨주면 된다. 부트스트랩로더로부터 forName()을 하고 싶다면 null을 넘기면 된다. 매개변수가 1개밖인 forName()는 current class loader로 부터 request 하고 type을 항상 초기화 된다. Class class의 instnace를 반환하고, 로그하지 못하면 ClassNotFoundException을 발생시킨다.


또 다른 방법은 사죵자정의 class loader의 loadClass()를 사용하는것이다, 이 메소드는 오러로딩되어 있는데 모두 String에는 fullName를 사용한다. loadClass()는 forName()과 비슷한 결과가 나오고, loadClass는 이미 Type이 로깅되어있으면 이전에 load한 type를 반환한다. 그러나 사용자 정의 클래스로더를 만든 사람 맘대로 할 수 있다. 잘 로딩되었자면 새롭게 로딩된 Class의 instance를 반환한다. 잘못되었으면 ClassNotFoundException 발생. 나만의 클래스로더 만들기는 뒤에서 보자.

 

boolean은 load가 잘 되면 link까지 할것인가를 나타낸다.

이전에 말했듯이 링킹은 세가지 단계를 가진다.

  1.  검증
  2. 준비
  3. (옵셔날) 레졸류션

boolean이 true이면 class의 instance를 resutnr하기 전에 load후에 link가 잘 되어 있는지 확인한다.

false이면 type의 link는 하지 않고 load만을 수행한다. 왜냐면 JVM구현이 링킨Time에 플렉서블하기 때문에 니가 false를 넘길때 loadClass()에서 type을 얻어올때 이미 링크되어 있을 수도 있고 그렇지 않을 수도 있기 때문이다.

 

두개의 파라미터를 가지는 loadClass는 Java1.1에서부터온 메소드이다. ( 쓸모없는 ; - 유산 ) 일반적으로 파라미터 1개의 load Class를 사용하며, 이는 파라미터 2개짜리에서 false를 호출한것곽 ㅏㅌ다. 1개짜리를 쓰면 load하고 return되나 link과 초기화는 JVM맘대로 한다.


forName()과 사용자정의 클래스로더의 loadClass()는 필요에따라서 써라. 별 달리 할게 없다면 forName()을 사용하라. forName()이 좀 더 직접적으로( 쉽고 빠르게 ) 사용할 수 있다. 로드, 링킹, 초기화가 다 된 놈이 필요하다면 forName()을 쓰면 된다.

loadClass()는 link됐을 수도 있고, 아닐 수도 있다. 싱글파라미터 forName()나, 3파라미터 forName()에서 초기화에 true를 주면 링크와 초기화가 이미 수행된 type를 반환받을 수 있다.

 


초기화는 JDBC에서 일반적으로 forName()으로 로딩하는 것을 보면 알 수 있다. JDBC드라이브는 어플리케이션에서 사용되어지기 위해서 로드뿐만 아니라 반드시 초기화 되어야만 한다. 각 JDBC 드라이브는 static initialize에서 DriverManager에 클래스를 등록하기 때문이다. 로드만 되면 static이 수행되지 않을꺼고, DriverManager에 등록하지 못할꺼고, 어플리케이션에서 사용하지 못할것이다. forName()을 쓰면 드라이브 초기화가 잘 될것이다.


forName()으로 못하는것들, 넷웍에 있거나, database에 있거나, 암호화되어 있거나, 심저이 인쇄지위에 있는게 필요하다면 loadClass()을 사용해야 한다.

사용자 정의 클래스로더를 만들어햐 하는 주요한 이유는  커스터마이징을 하기 위해서다.  ???

( forName()보다 더 시큐리티하게 사용가능 - 암호화 된 class화일을 풀어서 쓸 수 있음 )  ???

( class file format를 변경할 수 있음  - 물론 복호화 해야 할것임 )  ???

같은 namespace 에서 로드되지 않은 type들은 볼 수 없도록 작성할 수도 있음 ???

도메인으로 부터 프로텍션을 걸 수도 있음 ???

 


constance pool의 entry가 필요하면 그것을  가리키고 있는 type을 load할 class loader를 이용하여 필요한 type를 로등함.

Cat에서 Mouse를 사용하고 있고 Cat이 userdefind class loader로 부터 로딩이 되었다면, Mouse가 로딩되었는지 확인하고, 로딩이 되지 않았아면 Cat을 로딩한 클래스 로더로부터 Mouse를 request하게 된다.

Mouse라는 이름을 가진 class가 다른 name space에서 이미 로드되었다고 해도 위와 같이 동작한다.  ( 아마도 다른 class loader가 로드 했다는 말 같음 )

History

Last edited on 09/03/2007 21:53 by Chan

Comments (0)

You must log in to leave a comment. Please sign in.