- 浏览: 23023 次
- 性别:
- 来自: 南京
最新评论
-
cwj158:
请教下:
JSP转换为java程序为什么要交给WEB容器来做呢 ...
Tomcat源码系列4--Tomcat中Servlet处理流程 -
jilen:
个人感觉如果不是对JMX感兴趣,可以先跳过这部分,对其他源码阅 ...
Tomcat源码系列8--Tomcat的JMX管理2 -
xuhang1128:
学习了,看完您的文章自己再去看看能够更清晰点
Tomcat源码系列1--Tomcat启动流程1
前面讲到了JMX的体系,下面从Tomcat源代码启动过程分析MBeans组件注册到MBeanServer的过程 。
(org.apache.catalina.startup.Bootstrap.main(String))
public static void main(String args[]) { … if (daemon == null) { daemon = new Bootstrap(); try { daemon.init(); ★1 } catch (Throwable t) { t.printStackTrace(); return; } } try { String command = "start"; if (args.length > 0) { command = args[args.length - 1]; } if (command.equals("startd")) { args[0] = "start"; daemon.load(args); daemon.start(); } else if (command.equals("stopd")) { args[0] = "stop"; daemon.stop(); } else if (command.equals("start")) { daemon.setAwait(true); daemon.load(args); ★2 // Catalina的start方法被调用 daemon.start(); ★3 } else if (command.equals("stop")) { daemon.stopServer(args); } } catch (Throwable t) { t.printStackTrace(); } }
★1
daemon.init()会调用Bootstrap#createClassLoader方法,该方法会将对象名为StandardClassloader的MBean注册并返回Classloader。
(org.apache.catalina.startup.Bootstrap.createClassLoader(String, ClassLoader))
private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception { …… ClassLoader classLoader = ClassLoaderFactory.createClassLoader (unpacked, packed, urls, parent); // Retrieving MBean server MBeanServer mBeanServer = null; if (MBeanServerFactory.findMBeanServer(null).size() > 0) { mBeanServer = (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0); } else { mBeanServer = MBeanServerFactory.createMBeanServer(); } //注册Server类加载器MBeans ObjectName objectName = new ObjectName("Catalina:type=ServerClassLoader,name=" + name); mBeanServer.registerMBean(classLoader, objectName); return classLoader; }
common、server、shared三个classloader会被依序生成,并被注册到mBeanServer中去。这三个Classloader都是StandardClassloader,并且实现了StandardClassloaderMBean接口。因为StandardClassloaderMBean接口没有暴露任何的属性和方法,所以在Jconsole窗口中将看不到StandardClassloader的属性和方法显示。
★2
daemon.load(args)是Catalina载入的过程,standardServer、StandardService、Connector将会被依次初始化并完成Mbean的注册。
1) StandardServer初始化注册。
(org.apache.catalina.core.StandardServer.initialize())
public void initialize() throws LifecycleException { if (initialized) { log.info(sm.getString("standardServer.initialize.initialized")); return; } initialized = true; if( oname==null ) { try { //注册StandardServer的MBeans oname=new ObjectName( "Catalina:type=Server"); Registry.getRegistry(null, null) .registerComponent(this, oname, null ); } catch (Exception e) { log.error("Error registering ",e); } } // Initialize our defined Services for (int i = 0; i < services.length; i++) { services[i].initialize(); } }
2) StandardServer被注册后,它向外暴露了它的属性和await()和storeConfig()两个方法。
StandardService初始化并注册
(org.apache.catalina.core.StandardService.initialize())
public void initialize() throws LifecycleException { if (initialized) { log.info(sm.getString("standardService.initialize.initialized")); return; } initialized = true; if( oname==null ) { try { // StandardService的MBeans被注册 Container engine=this.getContainer(); domain=engine.getName(); oname=new ObjectName(domain + ":type=Service,serviceName="+name); this.controller=oname; Registry.getRegistry(null, null) .registerComponent(this, oname, null); } catch (Exception e) { log.error("Error registering ",e); } } } if( server==null ) { ServerFactory.getServer().addService(this); } //初始化我们定义的连接 synchronized (connectors) { for (int i = 0; i < connectors.length; i++) { connectors[i].initialize(); } }
StandardService被注册后,它向外暴露了它的属性和stop()和start()两个方法。在Jconsole中可以对这两个方法进行操作。
3) 对象名为“Catalina:type=Connector port=8080”、“Catalina:type=Connector port=8009”的Connector被注册。
(org.apache.catalina.connector.Connector.initialize())
public void initialize() throws LifecycleException { if (initialized) { log.info(sm.getString("coyoteConnector.alreadyInitialized")); return; } this.initialized = true; if( oname == null && (container instanceof StandardEngine)) { try { // we are loaded directly, via API - and no name was given to us StandardEngine cb=(StandardEngine)container; String encodedAddr = null; if (getAddress() != null) { encodedAddr = URLEncoder.encode(getAddress()); } String addSuffix=(getAddress()==null) ?"": ",address=" + encodedAddr; oname=new ObjectName(cb.getName() + ":type=Connector,port="+ getPort() + addSuffix); Registry.getRegistry(null, null) .registerComponent(this, oname, null); controller=oname; } catch (Exception e) { log.error( "Error registering connector ", e); } log.debug("Creating name for connector " + oname); }
ConnectorMbean暴露了它的属性和Start、stop、pause、resume、init、destroy等方法。可以在Jconsole中对这些方法进行操作。
★ 3
daemon.start()Catalina.start()StandardServer.start()
下面是Catalina.start()代码片段。
(org.apache.catalina.core.StandardServer.start())
public void start() throws LifecycleException { if (started) { log.debug(sm.getString("standardServer.start.started")); return; } //唤醒相关的生命周期监听者 lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; //启动我们定义的服务 synchronized (services) { for (int i = 0; i < services.length; i++) { if (services[i] instanceof Lifecycle) ((Lifecycle) services[i]).start(); } } //唤醒相关的生命周期监听者 lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); }
Tomcat的配置文件Server.xml中的Server元素中定义了Listener元素,如下所示:
<Server port="8005" shutdown="SHUTDOWN" debug="0"> ... <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" debug="0"/> ...
它将给org.apache.catalina.core.StandardServer添加一个org.apache.catalina.mbeans.ServerLifecycleListener类型的监听器,当StandardServer实例启动的时候,会触发一个START_EVENT事件,如StandardServer类中定义的那样:
public void start() throws LifecycleException { ... lifecycle.fireLifecycleEvent(START_EVENT, null); ... }
StandardServer对象停止的时候,会触发STOP_EVENT事件,如stop方法中定义的那样:
public void stop() throws LifecycleException { ... lifecycle.fireLifecycleEvent(STOP_EVENT, null); ... }
这些事件会导致ServerLifecycleListener中的lifecycleEvent方法被提交。下面展示了lifecycleEvent方法。
(org.apache.catalina.mbeans.ServerLifecycleListener.lifecycleEvent())
public void lifecycleEvent(LifecycleEvent event) { Lifecycle lifecycle = event.getLifecycle(); if (Lifecycle.START_EVENT.equals(event.getType())) { if (lifecycle instanceof Server) { createMBeans(); ... } ... else if (Lifecycle.STOP_EVENT.equals(event.getType())) { try { if (lifecycle instanceof Server) { destroyMBeans((Server)lifecycle); } if (lifecycle instanceof Service) { destroyMBeans((Service)lifecycle); } }
从上面的代码可以看出当lifecycleEvent被调用时,由于START_EVENT事件被触发,createMBeans方法被调用,Catalina中所有MBeans将会生成。当StandardServer关闭时,STOP_EVENT事件被触发,destroyMBeans方法被调用,所有的MBeans将被销毁。
1) START_EVENT事件被触发,lifecycleEvent(START_EVENT)被调用,它会调用createMBeans方法。
(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans())
protected void createMBeans() { try { MBeanFactory factory = new MBeanFactory(); createMBeans(factory);※1 createMBeans(ServerFactory.getServer());※2 } catch (MBeanException t) { Exception e = t.getTargetException(); if (e == null) e = t; log.error("createMBeans: MBeanException", e); } catch (Throwable t) { log.error("createMBeans: Throwable", t); } }
※1
该方法使用MBeanUtil类给MBeanFactory创建一个ObjectName并将其向MBean服务器注册。
protected void createMBeans(MBeanFactory factory) throws Exception { // Create the MBean for the MBeanFactory if (log.isDebugEnabled()) log.debug("Creating MBean for MBeanFactory " + factory); MBeanUtils.createMBean(factory); }
※2
该方法会将org.apache.catalina.Server对象创建模型MBean,使用for循环来迭代StandardServer实例中的所有Service对象。
protected void createMBeans(Server server) throws Exception { //为Server自身创建MBean if (log.isDebugEnabled()) log.debug("Creating MBean for Server " + server); //MBeanUtils.createMBean(server); if (server instanceof StandardServer) { ((StandardServer) server).addPropertyChangeListener(this); } // 为global NamingResources创建MBean(如果有的话) NamingResources resources = server.getGlobalNamingResources(); if (resources != null) { createMBeans(resources); } //为每个子服务创建MBeans Service services[] = server.findServices(); for (int i = 0; i < services.length; i++) { // FIXME - Warp object hierarchy not currently supported if (services[i].getContainer().getClass().getName().equals ("org.apache.catalina.connector.warp.WarpEngine")) { if (log.isDebugEnabled()) { log.debug("Skipping MBean for Service " + services[i]); } continue; } createMBeans(services[i]); } }
4) createMBeans(Service service) 创建一个MBean实例并调用createMBeans方法来为该服务所有的连接器和引擎创建MBean对象
(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Service))
protected void createMBeans(Service service) throws Exception { //为Service自身创建MBean if (log.isDebugEnabled()) log.debug("Creating MBean for Service " + service); //MBeanUtils.createMBean(service); if (service instanceof StandardService) { ((StandardService) service).addPropertyChangeListener(this); } // 为对应的连接器创建MBeans(8080,8009两个端口) Connector connectors[] = service.findConnectors(); for (int j = 0; j < connectors.length; j++) { createMBeans(connectors[j]); } // 为关联的Engine创建MBean Engine engine = (Engine) service.getContainer(); if (engine != null) { createMBeans(engine); } }
5) createMBeans(engine)(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Engine))
protected void createMBeans(Engine engine) throws Exception { //为Engine自身创建MBean if (log.isDebugEnabled()) { log.debug("Creating MBean for Engine " + engine); } //MBeanUtils.createMBean(engine); engine.addContainerListener(this); if (engine instanceof StandardEngine) { ((StandardEngine) engine).addPropertyChangeListener(this); } //为关联的嵌套组件创建MBean Realm eRealm = engine.getRealm(); if (eRealm != null) { if (log.isDebugEnabled()) log.debug("Creating MBean for Realm " + eRealm); //MBeanUtils.createMBean(eRealm); } // 为每个子Host创建MBeans Container hosts[] = engine.findChildren(); for (int j = 0; j < hosts.length; j++) { createMBeans((Host) hosts[j]); }
6) createMBeans(host) ((org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Host))
protected void createMBeans(Host host) throws Exception { //为Host自身创建MBeans if (log.isDebugEnabled()) { log.debug("Creating MBean for Host " + host); } //MBeanUtils.createMBean(host); host.addContainerListener(this); if (host instanceof StandardHost) { ((StandardHost) host).addPropertyChangeListener(this); } //为关联的嵌套组件创建MBean Realm eRealm = host.getParent().getRealm(); Realm hRealm = host.getRealm(); if ((hRealm != null) && (hRealm != eRealm)) { if (log.isDebugEnabled()) log.debug("Creating MBean for Realm " + hRealm); //MBeanUtils.createMBean(hRealm); } //为每个子Context创建MBeans Container contexts[] = host.findChildren(); for (int k = 0; k < contexts.length; k++) { createMBeans((Context) contexts[k]); } }
lifecycleEvent(START_EVENT)方法调用结束。调用会逐级返回, ((Lifecycle) services[i]).start()被调用。Deployer、GlobalRequestProcessor、JkHander、JkMain、JkWorkerEnv、Mapper、ThreadPool、Valve、ProtocolHandle等将会被注册。至此,Tomcat启动结束。JMX注册也完毕。
评论
发表评论
-
Tomcat源码系列7--Tomcat的JMX管理1
2011-03-31 14:40 1862接下来介绍一下在Tomcat ... -
Tomcat源码系列4--Tomcat中Servlet处理流程
2011-03-22 11:33 2437本次谈一下Servlet的处理流程,不当之处请各位指正。 在经 ... -
Tomcat源码系列3--Tomcat请求处理的流程
2011-03-20 12:36 1747本次讲解一下Tomcat请求处理的流程,不当之处还请comme ... -
Tomcat源码系列2--Tomcat启动流程2
2011-03-17 16:08 1427下面是standardEngine的启动和connector的 ... -
Tomcat源码系列1--Tomcat启动流程1
2011-03-17 15:39 1885最近在看Tomcat的源码,下面用博客记下看源码的一些心得。 ...
相关推荐
这个压缩包包含了两个版本的Tomcat源码:apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src,这两个版本分别代表了Tomcat在不同时间点的开发状态和技术特性。 首先,让我们从Apache Tomcat 6.0.39源码开始分析。...
在本项目中,"jmx监控weblogic,tomcat,websphere源码"涉及了使用JMX来监控三个主流的Java应用服务器:WebLogic、Tomcat和WebSphere。这些服务器都是企业级应用部署的常见选择,对它们的监控对于确保系统性能、稳定性...
通过对`apache-tomcat-9.0.8-src`源码的深入研究,我们可以了解到Tomcat如何处理网络请求,怎样管理Web应用,以及如何实现各种高级特性。这对于开发者来说是一份宝贵的学习资料,可以帮助他们更好地优化应用程序,...
8. **安全管理**:Tomcat支持角色基础的访问控制(RBAC),可以设置不同用户的访问权限,通过`tomcat-users.xml`配置用户和角色。 9. **日志系统**:Tomcat提供了详细的日志记录功能,帮助开发者调试和监控应用。...
Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...
对于初次接触Tomcat源码的开发者,可以从阅读`src/main/java`目录下的源码开始,重点关注`org.apache.catalina`包下的类,以及`org.apache.coyote`和`org.apache.jasper`等包。同时,`conf/server.xml`是配置整个...
8. **JMX(Java Management Extensions)**:Tomcat使用JMX来提供管理和监控功能,如监控服务器状态、性能指标等。`org.apache.tomcat.util.modeler`包下的类涉及JMX的实现。 9. **国际化和本地化**:Tomcat支持多...
### Tomcat源码研究知识点概览 #### 1.1 Catalina.bat脚本解析 - **脚本功能**:`catalina.bat`是Tomcat启动过程中的关键脚本之一,其主要作用在于构建合适的Java命令行参数,进而启动Tomcat服务。此脚本根据环境...
5. **JMX(Java Management Extensions)**:Tomcat支持JMX,允许管理员监控和管理服务器状态。查看`jmx`目录下的源码可以了解如何使用JMX注册和暴露管理MBean。 6. **配置解析**:Tomcat的配置文件如`server.xml`...
8. **性能优化**:Tomcat源码分析可以帮助开发者了解如何优化性能,如调整线程池大小,启用NIO(非阻塞I/O)模式,减少内存泄漏等。 9. **扩展性**:Tomcat源码允许开发者自定义Valves(请求处理管道中的组件)、...
- 调试Tomcat源码可以定位并解决运行时问题,例如性能瓶颈、内存泄漏或安全漏洞。 6. **扩展与定制** - Tomcat允许开发者自定义其行为,例如通过编写监听器、过滤器或servlet来扩展其功能。 - 可以通过编写自己...
【标题】"jakarta-tomcat-connectors-1.2.15-src.zip" 是一个包含Apache Tomcat连接器源代码的压缩包,主要用于帮助开发者深入理解Tomcat的工作原理,并进行自定义或扩展。 【描述】提到的"jakarta_tomcat_...
8. **JMX(Java Management Extensions)** - JMX用于监控和管理Tomcat实例,包括内存使用、线程状态、MBean注册等。 9. **错误处理和调试** - 错误页面和异常处理:通过`web.xml`配置,可以自定义错误页面和异常...
标题中的"apache-tomcat-9.0.44.tar.gz"是一个特定版本的Tomcat源码包,这里的9.0.44指的是Tomcat的版本号,而".tar.gz"是Linux/Unix系统中常见的归档压缩格式,用于将多个文件打包成一个单一的文件以便于传输和存储...
《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用服务器标准,尤其是Servlet和JSP规范。源码下载是开发者深入理解其内部工作原理的重要途径,本篇文章将围绕...
8. **JMX监控**:Tomcat使用Java Management Extensions (JMX) 提供监控和管理功能。通过MBeans(Managed Beans)可以获取服务器状态、配置和性能数据。 9. **日志系统**:Tomcat使用`org.apache.juli`包实现日志...
9. **JMX管理**:通过Java Management Extensions(JMX),开发者可以远程监控和管理Tomcat的运行状态,如查看线程池状态、内存使用情况等。 10. **性能优化**:优化Tomcat涉及调整线程池大小、缓存设置、减少上...
10. **性能优化**:Tomcat源码提供了很多可调整的参数,通过对这些参数的调整,可以优化内存使用、减少响应时间等,提升整体性能。 通过深入学习和理解"apache-tomcat-6.0.26-src"源码,开发者不仅可以提高Java Web...