Tomcat (5) 소스 코드 분석 Tomcat 시작 과정 - 클래스 로드 과정 깊이 이해

19716 단어 Tomcat
이것 은 우리 가 tomcat 의 다섯 번 째 글 을 깊이 이해 한 것 이다. 우리 의 생각 에 따 르 면 이번에 우 리 는 tomcat 의 커 넥 터 구성 요 소 를 분석 해 야 한다. 그러나 건물 주 는 심사숙고 한 후에 커 넥 터 구성 요 소 는 탁상공론 만 할 수 없고 소스 코드 를 깊이 들 어가 야 한다 고 생각 했다. 그러나 건물 주 는 본능적으로 우리 가 먼저 tomcat 의 작 동 과정 을 분석 하여 우리 와 이전 글 Tomcat( )Tomcat 을 할 수 있 도록 해 야 한다 고 생각 했다.맞물리다.시작 클래스 로 더 의 핵심 코드 가 시작 과정 에 있 기 때문에 저 는 먼저 tomcat 의 시작 과정 을 분석 하고 소스 코드 와 결합 하여 tomcat 의 클래스 로 더 가 어떻게 실현 되 는 지 알 아 보고 tomcat 의 클래스 로 더 를 철저히 이해 하기 로 했 습 니 다.
Tomcat 의 작 동 과정 이 매우 복잡 하기 때문에 건물 주가 작 동 과정 을 분리 분석 할 때 예전 에 말 한 것 처럼 작 동 과정 에 따라 분석 할 수 없다. 그렇지 않 으 면 글 의 편폭 이 너무 길 고 조리 가 뚜렷 하지 않 을 것 이다. Tomcat 의 작 동 과정 은 용기 의 생명 주 기 를 초기 화 하 는 것 을 포함 하고 JMX 의 관리 와 관련 되 며 우리 가 현재 분석 하고 있 는 클래스 로 더 도 포함한다. 그래서우 리 는 차원 분석 을 바 꿔 야 한다.
또 하 나 는 커 넥 터 와 용기 가 밀접 하 게 연결 되 어 있 기 때문에 커 넥 터 의 역할 은 http 요청 을 분석 하 는 것 입 니 다. 따라서 건물 주 는 우리 의 계획 이 변경 되 어야 한다 고 생각 합 니 다. 우 리 는 수명 주기 와 클래스 로 더 를 분석 한 후에 소스 코드 분석 커 넥 터 와 용 기 를 결합 하여 tomcat 의 핵심 구성 요소 가 HTTP 요청 을 받 은 후에 어떻게 작 동 하 는 지 알 아 보 겠 습 니 다.
그래서 오늘 우리 의 임 무 는 debug tomcat 소스 코드 로 tomcat 시작 과정의 모든 작업 을 분석 하 는 것 입 니 다.이 글 을 보기 전에 학생 들 은 우리 의 네 번 째 분석 tomcat 의 글 을 보고 tomcat 의 클래스 로 더 를 이해 하 기 를 바 랍 니 다.
다음은 이 글 의 디 렉 터 리 구조 입 니 다.
1.   tomcat,  main  
2.    init   
3.    setCatalinaHome   
4.    setCatalinaBase   
5.                  .    intiClassLoaders   
6.    createClassLoader   
7.      initClassLoaders     
8.     init    ,          ,      ?
9.                   ?    securityClassLoad   
10.    loadCorePackage   
11.    init   
12.    WebAppClassLoader,    startInternal   
13.    createClassLoader   
14. tomcat            

1. tomcat 를 시작 하여 main 방법 으로 들 어가 기
우 리 는 이전에 clone 에서 내 린 Tomcat - Source - code 소스 코드 를 열 고 Bootstrap 류 를 찾 아 main 방법 을 찾 아 451 줄 에 정지점 을 두 고 main 방법 을 시작 하여 디 버 깅 을 시작 합 니 다.
건물 주 는 이미 많은 주석 을 쓴 것 을 볼 수 있 습 니 다. 왜냐하면 건물 주 는 debug 가 지 났 기 때 문 입 니 다. 우 리 는 코드 를 보고 먼저 '수호' 대상 이 null 인지 아 닌 지 를 판단 한 다음 에 if 블록 에 들 어가 기본 구조 기의 Bootstrap 대상 을 만 들 고 주석 // Don't set daemon until init() has completed 이 있 습 니 다.init 방법 이 완성 되 기 전에 daemon 변 수 를 설정 하지 말 라 고 합 니 다. 뒤의 많은 절차 가 이 변수 에 의존 하기 때문에 초기 화 가 끝 난 후에 야 값 을 설정 할 수 있 습 니 다. 다시 보고 init 방법 에 들 어 갑 니 다.
2. init 진입 방법
이 방법 설명: Initialize daemon. 이 데 몬 을 초기 화 하 겠 다 고 밝 혔 습 니 다. 즉, 이 변수 Bootstrap 입 니 다.
이 방법 을 살 펴 보 자. 우선 setCatalinaHome() 방법, 즉 우리 가 가상 컴퓨터 를 시작 할 때 설정 한 VM 매개 변수 이다.
이 방법 으로 들 어가 보 겠 습 니 다.
3. setCatalinaHome 진입 방법
분명히 우 리 는 Catalina. home 을 설정 한 적 이 있 기 때문에 classpath 에 있 는 catalina. home 의 값 이 null 이 아니 기 때문에 직접 return 합 니 다. null 이 아니라면 프로젝트 루트 디 렉 터 리 에서 boostrap 의 jar 패 키 지 를 가 져 옵 니 다. 존재 한다 면 이전 디 렉 터 리 를 catalina. home 으로 설정 합 니 다. 존재 하지 않 는 다 면 프로젝트 루트 디 렉 터 리 를 catalina. home 으로 설정 합 니 다. 이것 이 setCatalina Home 방법의 논리 입 니 다.
4. setCatalinaBase 진입 방법
다음 단 계 는 setCatalinaBase 방법 을 실행 하 는 것 입 니 다. catalina.base 를 가 져 올 수 있 습 니 다. 직접 return 입 니 다. 존재 하지 않 으 면 catalina.homecatalina.base 로 설정 하고 catalina.home 도 비어 있 으 면 프로젝트 루트 디 렉 터 리 를 catatlina.base 로 설정 합 니 다.
5. 다음은 클래스 로 더 가 솜 씨 를 발휘 할 때 입 니 다. inticlassLoaders 에 들 어 가 는 방법
inticlassLoaders (), 여러 종류의 로 더 를 초기 화 합 니 다. 이 방법 에 들 어가 서 구체 적 인 논 리 를 봅 니 다.
우선, common 클래스 로 더 를 만 듭 니 다. 부모 클래스 로 더 는 null 입 니 다. 주의: 자바 가 추천 하 는 클래스 로 더 메커니즘 이 라면 부모 클래스 로 더 는 시스템 클래스 로 더 나 확장 클래스 로 더 여야 합 니 다. 그래서 이것 은 클래스 로 더 의 부모 위임 모델 에 현저히 어 긋 납 니 다. 자, tomcat 를 계속 봅 시다. 우 리 는 creatClassLoader 방법 에 들 어가 서 어떻게 실현 되 는 지 봅 시다.(이 방법 은 매우 길다. 우 리 는 중요 한 논리 에 주목한다):
6. createClassLoader 에 들 어 가 는 방법
private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {
        //  /org/apache/catalina/startup/catalina.properties      key    
        // common.loader     Value=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar
        String value = CatalinaProperties.getProperty(name + ".loader");
        //      (    ),    null
        if ((value == null) || (value.equals(""))){
            return parent;
        }
        //                 
        value = replace(value);

        //Repository ClassLoaderFactory           ,  2   , location, type,               
        List repositories = new ArrayList();
        /*
              ,         value             
        */  

        //                  class   ,
        // StandardClassLoader     java.net.URLClassLoader ,  URLClassLoader          .
        //            null, URLClassLoader         .
        //   , common              ,        
        ClassLoader classLoader = ClassLoaderFactory.createClassLoader//       ,   parent  0, 
            (repositories, parent);

        // Retrieving MBean server //     JMX     bean,        
        MBeanServer mBeanServer = null;
        if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
            mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
        } else {
            mBeanServer = ManagementFactory.getPlatformMBeanServer();
        }

        // Register the server classloader
        ObjectName objectName =
            new ObjectName("Catalina:type=ServerClassLoader,name=" + name);
        //       .
        mBeanServer.registerMBean(classLoader, objectName);

        return classLoader;

    }
````
           ,            :
1.  `/org/apache/catalina/startup/catalina.properties `        lib     jar    .    key (   common.loader、server.loader、shared.loader)    value            .      .        .
2.               ,   jar     .
3.   `ClassLoaderFactory.createClassLoader(repositories, parent)`  ,            `java.net.URLClassLoader`   `StandardClassLoader`    jar         ,        URLClassLoader     ,       crateClassLoader         , array    jar     ,           null   `StandardClassLoader`       .
4.  ClassLoader    JMX   (            ,      ,    )。

![](http://upload-images.jianshu.io/upload_images/4236553-4adc8d0b36c05114.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    `StandardClassLoader`     ,    ,       URLClassLoader      :

![](http://upload-images.jianshu.io/upload_images/4236553-973fd96d79b6594d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  URLClassLoader         SecureClassLoader      ,   SecureClassLoader      ClassLoader      ,               .     .





"se-preview-section-delimiter">
##### 7. initClassLoaders `commonLoader = createClassLoader("common", null);`, null, null ? key key value null, null, common . catalinaloader sharedLoader , createClassLoader , , null, common . ? debug : ![](http://upload-images.jianshu.io/upload_images/4236553-fd0d2db752af5723.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](http://upload-images.jianshu.io/upload_images/4236553-e81758f680ec5dff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) , , , .
"se-preview-section-delimiter">
### 8. init , , ? ![](http://upload-images.jianshu.io/upload_images/4236553-774ddc72bda64f5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) catalinaLoader . . , , . ![](http://upload-images.jianshu.io/upload_images/4236553-05cbefb1693430cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
"se-preview-section-delimiter">
#### 9. ? securityClassLoad ![](http://upload-images.jianshu.io/upload_images/4236553-a88757e3f188b647.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](http://upload-images.jianshu.io/upload_images/4236553-7b0ecfa890763864.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) , Tomcat , ClassLoader catalinaLoader, ,Tomcat catalinaLoader 。 securityClassLoad Tomcat class, : * Tomcat class, org.apache.catalina.core class; * org.apache.catalina.loader.WebappClassLoader$PrivilegedFindResourceByName; * Tomcat session class, org.apache.catalina.session class; * Tomcat class, org.apache.catalina.util class; * javax.servlet.http.Cookie; * Tomcat class, org.apache.catalina.connector class; * Tomcat class, org.apache.catalina.util class;
"se-preview-section-delimiter">
#### 10. loadCorePackage Tomcat class loadCorePackage , :
"se-preview-section-delimiter">
```java private static final void loadCorePackage(ClassLoader loader) throws Exception { final String basePackage = "org.apache.catalina.core."; loader.loadClass (basePackage + "AccessLogAdapter"); loader.loadClass (basePackage + "ApplicationContextFacade$1"); loader.loadClass (basePackage + "ApplicationDispatcher$PrivilegedForward"); loader.loadClass (basePackage + "ApplicationDispatcher$PrivilegedInclude"); loader.loadClass (basePackage + "AsyncContextImpl"); loader.loadClass (basePackage + "AsyncContextImpl$DebugException"); loader.loadClass (basePackage + "AsyncContextImpl$1"); loader.loadClass (basePackage + "AsyncContextImpl$PrivilegedGetTccl"); loader.loadClass (basePackage + "AsyncContextImpl$PrivilegedSetTccl"); loader.loadClass (basePackage + "AsyncListenerWrapper"); loader.loadClass (basePackage + "ContainerBase$PrivilegedAddChild"); loader.loadClass (basePackage + "DefaultInstanceManager$1"); loader.loadClass (basePackage + "DefaultInstanceManager$2"); loader.loadClass (basePackage + "DefaultInstanceManager$3"); loader.loadClass (basePackage + "DefaultInstanceManager$AnnotationCacheEntry"); loader.loadClass (basePackage + "DefaultInstanceManager$AnnotationCacheEntryType"); loader.loadClass (basePackage + "ApplicationHttpRequest$AttributeNamesEnumerator"); }

catalinaClassLoader 가 이 가방 의 클래스 를 불 러 왔 습 니 다. 이전 이해 에 따 르 면 catalinaClassLoader 가 불 러 온 클래스 는 Tomcat 용기 의 개인 클래스 로 더 입 니 다. 불 러 오 는 경로 의 class 는 Webapp 에 보이 지 않 습 니 다.
11. init 로 돌아 가 는 방법
먼저 로 그 를 인쇄 한 다음 클래스 catalinaLoader 클래스 로 더 org.apache.catalina.startup.Catalina 클래스 를 불 러 옵 니 다. 이 어 이 클래스 의 대상 을 만 듭 니 다. "시작 대상 인 스 턴 스" 라 는 뜻 으로 startupInstance 를 만 든 다음 이 인 스 턴 스 를 반사 호출 하 는 setParent ClassLoader 방법 을 사용 합 니 다. 매개 변 수 는 shared Loader 입 니 다. 이 인 스 턴 스 의 부모 클래스 로 더 를 shared Loader 라 고 표시 합 니 다.
마지막 으로 catalina Daemon 을 이 인 스 턴 스 로 설정 합 니 다.
12. WebAppClassLoader 를 찾 아 startInternal 에 들 어 가 는 방법
우 리 는 소스 코드 를 통 해 comonClassLoader, catalina ClassLoader, shared Loader 를 초기 화 했다 는 것 을 알 게 되 었 습 니 다. 그러나 우 리 는 지난 글 의 그림 을 떠 올 리 면 뭔 가 부족 한 것 같 습 니 다.
WebAppClassLoader 는 요?
웹 앱 ClassLoaser 는 각 웹 앱 의 개인 적 인 클래스 로 더 입 니 다. 로 딩 경로 에 있 는 class 는 현재 웹 앱 에 만 보 입 니 다. 그러면 그 는 어떻게 초기 화 했 습 니까? 웹 앱 ClassLoaser 의 초기 화 시간 은 이 세 가지 종류의 로 더 를 초기 화 하 는 시간 과 다 릅 니 다. 웹 앱 ClassLoaser 는 Context 와 밀접 한 관 계 를 가지 기 때문에 org. apache. catalina. core. StandardCo 를 어떻게 초기 화 합 니까?ntext 는 함께 WebAppClassLoader 를 초기 화 합 니 다. 이 클래스 에서 startInternal 방법 은 초기 화 클래스 로 더 의 논 리 를 포함 하고 핵심 소스 코드 는 다음 과 같 습 니 다.
    @Override
    protected synchronized void startInternal() throws LifecycleException {
         if (getLoader() == null) {
              WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
              webappLoader.setDelegate(getDelegate());
              setLoader(webappLoader);
        }
        if ((loader != null) && (loader instanceof Lifecycle)) {
              ((Lifecycle) loader).start();
        }
    }

먼저 WebAppClassLoader 를 만 든 다음 에 setLoader (webappLoader) 를 만 들 고 start 방법 을 호출 합 니 다. 이 방법 은 템 플 릿 방법 입 니 다. 내부 에 startInternal 방법 이 하위 클래스 에 사용 되 고 있 습 니 다. WebAppClassLoader 의 startInternal 방법 핵심 실현 을 보 겠 습 니 다.
    @Override
    protected void startInternal() throws LifecycleException {
            classLoader = createClassLoader();
            classLoader.setResources(container.getResources());
            classLoader.setDelegate(this.delegate);
            classLoader.setSearchExternalFirst(searchExternalFirst);
            if (container instanceof StandardContext) {
                classLoader.setAntiJARLocking(
                        ((StandardContext) container).getAntiJARLocking());
                classLoader.setClearReferencesStatic(
                        ((StandardContext) container).getClearReferencesStatic());
                classLoader.setClearReferencesStopThreads(
                        ((StandardContext) container).getClearReferencesStopThreads());
                classLoader.setClearReferencesStopTimerThreads(
                        ((StandardContext) container).getClearReferencesStopTimerThreads());
                classLoader.setClearReferencesHttpClientKeepAliveThread(
                        ((StandardContext) container).getClearReferencesHttpClientKeepAliveThread());
            }

            for (int i = 0; i < repositories.length; i++) {
                classLoader.addRepository(repositories[i]);
            }

    }

13. createClassLoader 에 들 어 가 는 방법
우선 classLoader = createClassLoader(); 클래스 로 더 를 만 들 고 현재 웹 앱 의 다음 context 클래스 자원 으로 자원 경 로 를 설정 합 니 다. 마지막 으로 createClassLoader 의 실현 을 살 펴 보 겠 습 니 다.

    /**
     * Create associated classLoader.
     */
    private WebappClassLoader createClassLoader()
        throws Exception {

        Class> clazz = Class.forName(loaderClass);
        WebappClassLoader classLoader = null;

        if (parentClassLoader == null) {
            parentClassLoader = container.getParentClassLoader();
        }
        Class>[] argTypes = { ClassLoader.class };
        Object[] args = { parentClassLoader };
        Constructor> constr = clazz.getConstructor(argTypes);
        classLoader = (WebappClassLoader) constr.newInstance(args);

        return classLoader;

    }

이 곳 의 loaderClass 는 문자열 org.apache.catalina.loader.WebappClassLoader 입 니 다. 우선 반 사 를 통 해 classLoader 를 실례 화 합 니 다. 이제 웹 앱 ClassLoader 는 StandardContext 가 초기 화 될 때 실례 화 되 었 고, 웹 앱 ClassLoader 와 Context 가 밀접 한 관 계 를 증명 합 니 다.
14. omcat 클래스 로드 구조 시스템 생 성 완료
이로써 우리 의 Tomcat 류 로 딩 구조 체 계 는 구축 되 었 습 니 다. 정말 TMD 가 복잡 합 니 다!!! 하지만 소스 코드 를 읽 는 것 은 우리 의 수준 을 향상 시 키 는 가장 빠 른 수단 이라는 것 을 기억 하 세 요. 소스 코드 에서 대사 들 의 디자인 모델 과 각종 고급 용법 은 우리 의 공력 을 크게 증가 시 킬 것 입 니 다. 계속 힘 내세 요!!

좋은 웹페이지 즐겨찾기