亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

tomcat類加載機制是什么

發布時間:2021-07-23 22:41:50 來源:億速云 閱讀:146 作者:chen 欄目:編程語言

這篇文章主要介紹“tomcat類加載機制是什么”,在日常操作中,相信很多人在tomcat類加載機制是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”tomcat類加載機制是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一、tomcat類加載器繼承圖

tomcat類加載機制是什么

tomcat類加載器的集成體系,包含兩部分:

1.上半部分是jdk自帶的,包含:啟動類加載器,擴展類加載器,應用類加載器,這里不展開講解。如果想了解,可以查看sun.misc.Launcher.Launcher()和java.lang.ClassLoader.loadClass(String, boolean)源碼

2.下半部分是tomcat的自定義類加載器,包含:

a)commonClassLoader:通過${tomcatpath}/conf/catalina.properties中的common.loader配置,通常加載tomcat和webapp共享的class

b) catalinaClassLoader: 通過${tomcatpath}/conf/catalina.properties中的server.loader配置,加載tomcat需要的class,對webapp不可見

c) sharedClassLoader:通過${tomcatpath}/conf/catalina.properties中的shared.loader配置, 加載webapp們共享的class,對tomcat容器不可見

d) webappClassLoader: 這個類加載器,就是加載我們寫的應用程序class的。通常說的tomcat打破雙親委派就是說的它

二、源碼

1.初始化自定義加載器

// org.apache.catalina.startup.Bootstrap.initClassLoaders()
private void initClassLoaders() {
    try {
        commonLoader = createClassLoader("common", null);
        if (commonLoader == null) {
            // no config file, default to this loader - we might be in a 'single' env.
            commonLoader = this.getClass().getClassLoader();
        }
        catalinaLoader = createClassLoader("server", commonLoader);
        sharedLoader = createClassLoader("shared", commonLoader);
    } catch (Throwable t) {
        handleThrowable(t);
        log.error("Class loader creation threw exception", t);
        System.exit(1);
    }
}

2.初始化webappclassloader

org.apache.catalina.loader.WebappLoader.startInternal()
protected void startInternal() throws LifecycleException {
 
    if (log.isDebugEnabled())
        log.debug(sm.getString("webappLoader.starting"));
 
    if (context.getResources() == null) {
        log.info("No resources for " + context);
        setState(LifecycleState.STARTING);
        return;
    }
 
    // Construct a class loader based on our current repositories list
    try {
        // 創建classloader,并將父classloader設置成sharedClassLoader
        classLoader = createClassLoader();
        classLoader.setResources(context.getResources());
        // 設置委派模式
        classLoader.setDelegate(this.delegate);
 
        // Configure our repositories
        setClassPath();
 
        setPermissions();
 
        // 開始類加載
        ((Lifecycle) classLoader).start();
 
        String contextName = context.getName();
        if (!contextName.startsWith("/")) {
            contextName = "/" + contextName;
        }
        ObjectName cloname = new ObjectName(context.getDomain() + ":type=" +
                classLoader.getClass().getSimpleName() + ",host=" +
                context.getParent().getName() + ",context=" + contextName);
        Registry.getRegistry(null, null)
            .registerComponent(classLoader, cloname, null);
 
    } catch (Throwable t) {
        t = ExceptionUtils.unwrapInvocationTargetException(t);
        ExceptionUtils.handleThrowable(t);
        log.error( "LifecycleException ", t );
        throw new LifecycleException("start: ", t);
    }
 
    setState(LifecycleState.STARTING);
}
 
 
private WebappClassLoaderBase createClassLoader()
    throws Exception {
 
    Class<?> clazz = Class.forName(loaderClass);
    WebappClassLoaderBase classLoader = null;
 
    if (parentClassLoader == null) {
        parentClassLoader = context.getParentClassLoader();
    } else {
        context.setParentClassLoader(parentClassLoader);
    }
    Class<?>[] argTypes = { ClassLoader.class };
    Object[] args = { parentClassLoader };
    Constructor<?> constr = clazz.getConstructor(argTypes);
    classLoader = (WebappClassLoaderBase) constr.newInstance(args);
 
    return classLoader;
}

3.裝配應用class文件

// org.apache.catalina.loader.WebappClassLoaderBase.start()
public void start() throws LifecycleException {
 
    state = LifecycleState.STARTING_PREP;
     
    // 掃描 /WEB-INF/classes 下的class
    WebResource[] classesResources = resources.getResources("/WEB-INF/classes");
    for (WebResource classes : classesResources) {
        if (classes.isDirectory() && classes.canRead()) {
            localRepositories.add(classes.getURL());
        }
    }
 
 
    // 掃描 /WEB-INF/lib 下的jar
    WebResource[] jars = resources.listResources("/WEB-INF/lib");
    for (WebResource jar : jars) {
        if (jar.getName().endsWith(".jar") && jar.isFile() && jar.canRead()) {
            localRepositories.add(jar.getURL());
            // 記錄jar的修改時間,用于熱更新
            jarModificationTimes.put(
                    jar.getName(), Long.valueOf(jar.getLastModified()));
        }
    }
 
    state = LifecycleState.STARTED;
}

4.tomcat熱更新:

// org.apache.catalina.loader.WebappLoader.backgroundProcess()
public void backgroundProcess() {
    // reloadable:是否開啟熱更新
    // modified():判斷jar和class是否有修改(這里會導致cpu瞬間高)
    if (reloadable && modified()) {
        try {
            Thread.currentThread().setContextClassLoader
                (WebappLoader.class.getClassLoader());
            if (context != null) {
                context.reload();
            }
        } finally {
            if (context != null && context.getLoader() != null) {
                Thread.currentThread().setContextClassLoader
                    (context.getLoader().getClassLoader());
            }
        }
    }
}

5.加載一個class文件的過程:

// org.apache.catalina.loader.WebappClassLoaderBase.loadClass(String)
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
 
        Class<?> clazz = null;
 
        // Log access to stopped class loader
        checkStateForClassLoading(name);
 
        // (0) Check our previously loaded local class cache
        // 從本地緩存查找
        clazz = findLoadedClass0(name);
        if (clazz != null) {
            if (log.isDebugEnabled())
                log.debug("  Returning class from cache");
            if (resolve)
                resolveClass(clazz);
            return clazz;
        }
 
        // (0.1) Check our previously loaded class cache
        // 從父類類加載器緩存查找
        clazz = findLoadedClass(name);
        if (clazz != null) {
            if (log.isDebugEnabled())
                log.debug("  Returning class from cache");
            if (resolve)
                resolveClass(clazz);
            return clazz;
        }
 
        // (0.2) Try loading the class with the system class loader, to prevent
        //       the webapp from overriding Java SE classes. This implements
        //       SRV.10.7.2
        String resourceName = binaryNameToPath(name, false);
 
        ClassLoader javaseLoader = getJavaseClassLoader();
        boolean tryLoadingFromJavaseLoader;
        try {
            // Use getResource as it won't trigger an expensive
            // ClassNotFoundException if the resource is not available from
            // the Java SE class loader. However (see
            // https://bz.apache.org/bugzilla/show_bug.cgi?id=58125 for
            // details) when running under a security manager in rare cases
            // this call may trigger a ClassCircularityError.
            // See https://bz.apache.org/bugzilla/show_bug.cgi?id=61424 for
            // details of how this may trigger a StackOverflowError
            // Given these reported errors, catch Throwable to ensure any
            // other edge cases are also caught
            URL url;
            if (securityManager != null) {
                PrivilegedAction<URL> dp = new PrivilegedJavaseGetResource(resourceName);
                url = AccessController.doPrivileged(dp);
            } else {
                url = javaseLoader.getResource(resourceName);
            }
            tryLoadingFromJavaseLoader = (url != null);
        } catch (Throwable t) {
            // Swallow all exceptions apart from those that must be re-thrown
            ExceptionUtils.handleThrowable(t);
            // The getResource() trick won't work for this class. We have to
            // try loading it directly and accept that we might get a
            // ClassNotFoundException.
            tryLoadingFromJavaseLoader = true;
        }
 
        // 嘗試用加載String類(即啟動類加載器)的類加載器加載
        if (tryLoadingFromJavaseLoader) {
            try {
                clazz = javaseLoader.loadClass(name);
                if (clazz != null) {
                    if (resolve)
                        resolveClass(clazz);
                    return clazz;
                }
            } catch (ClassNotFoundException e) {
                // Ignore
            }
        }
 
        // (0.5) Permission to access this class when using a SecurityManager
        if (securityManager != null) {
            int i = name.lastIndexOf('.');
            if (i >= 0) {
                try {
                    securityManager.checkPackageAccess(name.substring(0,i));
                } catch (SecurityException se) {
                    String error = "Security Violation, attempt to use " +
                        "Restricted Class: " + name;
                    log.info(error, se);
                    throw new ClassNotFoundException(error, se);
                }
            }
        }
 
        // 判斷是否委派給父類加載器
        boolean delegateLoad = delegate || filter(name, true);
 
        // (1) Delegate to our parent if requested
        // 委派給父類加載器(sharedClassLoader),符合委派雙親
        if (delegateLoad) {
            if (log.isDebugEnabled())
                log.debug("  Delegating to parent classloader1 " + parent);
            try {
                clazz = Class.forName(name, false, parent);
                if (clazz != null) {
                    if (log.isDebugEnabled())
                        log.debug("  Loading class from parent");
                    if (resolve)
                        resolveClass(clazz);
                    return clazz;
                }
            } catch (ClassNotFoundException e) {
                // Ignore
            }
        }
 
        // (2) Search local repositories
        // 在本地存儲庫查找并加載
        if (log.isDebugEnabled())
            log.debug("  Searching local repositories");
        try {
            clazz = findClass(name);
            if (clazz != null) {
                if (log.isDebugEnabled())
                    log.debug("  Loading class from local repository");
                if (resolve)
                    resolveClass(clazz);
                return clazz;
            }
        } catch (ClassNotFoundException e) {
            // Ignore
        }
 
        // (3) Delegate to parent unconditionally
        // 即使沒有委派,最后也執行一次委派
        if (!delegateLoad) {
            if (log.isDebugEnabled())
                log.debug("  Delegating to parent classloader at end: " + parent);
            try {
                clazz = Class.forName(name, false, parent);
                if (clazz != null) {
                    if (log.isDebugEnabled())
                        log.debug("  Loading class from parent");
                    if (resolve)
                        resolveClass(clazz);
                    return clazz;
                }
            } catch (ClassNotFoundException e) {
                // Ignore
            }
        }
    }
 
    throw new ClassNotFoundException(name);
}

到此,關于“tomcat類加載機制是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴安县| 城固县| 岢岚县| 鄂伦春自治旗| 仁布县| 安国市| 镶黄旗| 禹城市| 宾阳县| 土默特左旗| 资溪县| 平谷区| 巧家县| 高清| 柳州市| 新竹市| 巩留县| 临安市| 丁青县| 涿州市| 瓦房店市| 江北区| 青海省| 读书| 崇礼县| 定州市| 桃园县| 宜兰市| 德昌县| 景洪市| 罗山县| 厦门市| 盘锦市| 康平县| 昭通市| 鸡西市| 和林格尔县| 丽江市| 平潭县| 林周县| 杭锦后旗|