- 浏览: 22665 次
- 性别:
- 来自: 南京
最新评论
-
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 1843接下来介绍一下在Tomcat ... -
Tomcat源码系列4--Tomcat中Servlet处理流程
2011-03-22 11:33 2401本次谈一下Servlet的处理流程,不当之处请各位指正。 在经 ... -
Tomcat源码系列3--Tomcat请求处理的流程
2011-03-20 12:36 1724本次讲解一下Tomcat请求处理的流程,不当之处还请comme ... -
Tomcat源码系列2--Tomcat启动流程2
2011-03-17 16:08 1395下面是standardEngine的启动和connector的 ... -
Tomcat源码系列1--Tomcat启动流程1
2011-03-17 15:39 1857最近在看Tomcat的源码,下面用博客记下看源码的一些心得。 ...
相关推荐
java项目,自己做的项目利用jmx监控weblogic,tomcat,websphere源码
Tomcat源码研究.pdf。Catalina脚本解析,Tomcat启动遇到的常见问题,架构探讨,JMX在tomcat中的应用,容器初探,生命周期
资源是关于tomcat深入剖析的源码. ...本书从最基本的HTTP请求开始,直至使用JMX技术管理Tomcat中的应用程序,逐一剖析Tomcat的基本功能模块,并配以示例代码,使读者可以逐步实现自己的Web服务器。
总体架构:1、面向组件架构2、基于JMX3、事件侦听tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成,如Server、Service、Connector等,并基于JMX管理这些组件,另外实现以上接口的组件也...
Commons-Modeler 提供了建模兼容JMX规范的 Mbean的机制. Net Net 是一个网络工具集,基于 NetComponents 代码,包括 FTP 客户端等等。 Pool Commons-Pool 提供了通用对象池接口,一个用于创建模块化对象池的工具包...
Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...
8个目标文件 简单 JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器 Java编写的HTML浏览器源代码,一个很简单甚至不算是...
|->|->(抽离tomcat源码之生命周期) |->|->(二进制文件加密) |-> (jmx使用演示) |-> (mongodb使用演示) |-> (GUI聊天器-客户端+服务端原始码) |-> (自己实现动态代理) |-> (json与地图,列表,对象之间...
java系统源码 mountain 工程 后端工程启动后访问URL: 访问url: 更新日期-20200415 buglist 权限管理一些bug修改 newlist 用户管理添加昵称 更新日期-20200326 buglist 在idea中执行package打包时,打包2次,是因为...
1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...
MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...
java卡牌游戏源码 弱联网服务端架构 HTTPServer说明 此Demo为个人兴趣所写,是本人通过半年多服务端学习的一次大胆尝试,将之前学到的很多知识都融合在一起,除了对以前的知识整合之外,也不断进行改变和创新!目前...
1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...
1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...
1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...
MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...
MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...
MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...