设为首页 收藏本站
查看: 370|回复: 0

[经验分享] 细说Tomcat如何打破双亲委派(续1)

[复制链接]

尚未签到

发表于 2017-2-4 13:21:49 | 显示全部楼层 |阅读模式
  在上一篇文章里面分析WebappClassLoader.loadClass,了解了Tomcat是如何打破双亲委派的. 有兴趣的可以参考. 细说Tomcat如何打破双亲委派(有源码和图) 
  但是上面的分析偏重于流程,没有分析ClassLoader是如何加按照顺序寻址,然后加载对应的Class到二进制流中.
  WebappClassLoader.loadClass在违背双亲委派规则,自己寻址class文件时,就会调用下面的函数,函数已经添加了注释. 此函数依旧没有分析是如何寻址文件的,寻址文件的代码在findResourceInternal()中,它同时包括了对Jar,class, properties的寻址, 稍后有空在对此函数进行分析.

    /**
* Find the specified class in our local repositories, if possible.  If
* not found, throw <code>ClassNotFoundException</code>.
*
* @param name Name of the class to be loaded
*
* @exception ClassNotFoundException if the class was not found
*/
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
if (log.isDebugEnabled())
log.debug("    findClass(" + name + ")");
// Cannot load anything from local repositories if class loader is stopped
if (!started) {
throw new ClassNotFoundException(name);
}
//--默认为NULL, security获取package.definition的定义,默认的定义可以在如下地址找到
//--${TOMCAT_HOME}\bin\bootstrap.jar\org\apache\catalina\startup\catalina.properties//--package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
//--如果加载的package被包含了,则抛出异常,加载失败
// (1) Permission to define this class when using a SecurityManager
if (securityManager != null) {
int i = name.lastIndexOf('.');
if (i >= 0) {
try {
if (log.isTraceEnabled())
log.trace("      securityManager.checkPackageDefinition");
securityManager.checkPackageDefinition(name.substring(0,i));
} catch (Exception se) {
if (log.isTraceEnabled())
log.trace("      -->Exception-->ClassNotFoundException", se);
throw new ClassNotFoundException(name, se);
}
}
}
//-- 从父类查找Class(默认会跳过), 因为hasExternalRepositories && searchExternalFirs为false
//-- Ask our superclass to locate this class, if possible
// (throws ClassNotFoundException if it is not found)
Class<?> clazz = null;
try {
if (log.isTraceEnabled())
log.trace("      findClassInternal(" + name + ")");
if (hasExternalRepositories && searchExternalFirst) {
try {
clazz = super.findClass(name);
} catch(ClassNotFoundException cnfe) {
// Ignore - will search internal repositories next
} catch(AccessControlException ace) {
log.warn("WebappClassLoader.findClassInternal(" + name
+ ") security exception: " + ace.getMessage(), ace);
throw new ClassNotFoundException(name, ace);
} catch (RuntimeException e) {
if (log.isTraceEnabled())
log.trace("      -->RuntimeException Rethrown", e);
throw e;
}
}
//-开始从本地加载Class
if ((clazz == null)) {
try {
clazz = findClassInternal(name);
} catch(ClassNotFoundException cnfe) {
if (!hasExternalRepositories || searchExternalFirst) {
throw cnfe;
}
} catch(AccessControlException ace) {
log.warn("WebappClassLoader.findClassInternal(" + name
+ ") security exception: " + ace.getMessage(), ace);
throw new ClassNotFoundException(name, ace);
} catch (RuntimeException e) {
if (log.isTraceEnabled())
log.trace("      -->RuntimeException Rethrown", e);
throw e;
}
}
//--hasExternalRepositories:如果之前添加了外部路径,可以尝试从外部路径查找Class
if ((clazz == null) && hasExternalRepositories && !searchExternalFirst) {
try {
clazz = super.findClass(name);
} catch(AccessControlException ace) {
log.warn("WebappClassLoader.findClassInternal(" + name
+ ") security exception: " + ace.getMessage(), ace);
throw new ClassNotFoundException(name, ace);
} catch (RuntimeException e) {
if (log.isTraceEnabled())
log.trace("      -->RuntimeException Rethrown", e);
throw e;
}
}
//--如果都尝试了依旧找不到,就抛出异常了
if (clazz == null) {
if (log.isDebugEnabled())
log.debug("    --> Returning ClassNotFoundException");
throw new ClassNotFoundException(name);
}
} catch (ClassNotFoundException e) {
if (log.isTraceEnabled())
log.trace("    --> Passing on ClassNotFoundException");
throw e;
}
// Return the class we have located
if (log.isTraceEnabled())
log.debug("      Returning class " + clazz);
if (log.isTraceEnabled()) {
ClassLoader cl;
if (Globals.IS_SECURITY_ENABLED){
cl = AccessController.doPrivileged(
new PrivilegedGetClassLoader(clazz));
} else {
cl = clazz.getClassLoader();
}
log.debug("      Loaded by " + cl.toString());
}
return (clazz);
}

  总结一下,就是这个函数默认的是直接在Tomcat本地查找Class,但是提供了参数可以控制从父类,或者指定的目录去查找Class.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-337477-1-1.html 上篇帖子: 使用tomcat的compression来提高网页加载速度 下篇帖子: TOMCAT下创建HTTPS项目的方法(转)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表