【问题标题】:Tomcat class-reloading for JSPsJSP 的 Tomcat 类重载
【发布时间】:2012-06-07 14:45:12
【问题描述】:

在重新加载 JSP 时,类重新加载在 Tomcat 中是如何工作的(我说的是内部架构)?

我知道每个 JSP 都被编译成一个 Java 类。但是考虑到类加载器不允许卸载类并且不会收集太多垃圾,类加载器(每个 Web 应用程序是唯一的)如何重新加载这些生成的类?

【问题讨论】:

  • 我不同意“不收集太多垃圾”,因为 Tomcat 以在几次热重新部署后内存不足而闻名。
  • 是的,@maksimov,你是对的。也许我还应该添加一个问题来询问 Tomcat 降低内存不足错误概率的策略是什么。
  • Tomcat 的一些信息。很高兴知道他们正在使用 ECJ 增量编译器进行 JSP 编译。
  • @maksimov Tomcat 在几次热部署后内存不足并不为人所知。取而代之的是,许多 Web 应用程序编写得很糟糕,并且其中很多都在 Tomcat 实例上运行。一个正确编写的 Web 应用程序可以重新部署数百次,而无需重新启动 Tomcat,也不会耗尽内存。
  • @ChristopherSchultz 我不会争辩,因为它可能只通过 Eclipse 运行——根据我的经验和其他人的经验(谷歌在这里提供帮助)。我知道这很可能是由于不同的执行过程和方法造成的,但问题仍然存在。

标签: java tomcat classloader dynamic-class-loaders


【解决方案1】:

JasperLoader 实例是加载 jsp 生成的 servlet 的类加载器。

jsp 编译器在生成更新的 servlet 类文件时“丢弃”(设置为 null)旧的 JasperLoader 实例。

引用来自JspServletWrapper.setServletLastModifiedTime的cmets:

确实需要卸载旧类但不能这样做。做 下一个最好的事情就是扔掉 JspLoader 所以 将创建一个新的加载器,它将加载新的 类。

另见where this method is called after compiling

【讨论】:

    【解决方案2】:

    标准的 Java 类加载器从不卸载类。 Tomcat 有自己的类加载器,它可以用新实例替换一个类的旧实例,然后孤立旧实例,使其以通常的方式可供垃圾收集器使用。

    在某处我读到,如果某个类在某个指定的时间段内未使用,Tomcat 将卸载它。但目前我找不到任何参考。

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 我已经检查了代码。但是,我不明白的是:在 Java 中,每个类加载器都有一个加载类的列表(请参阅 ClassLoader 中的私有属性类)。 addClass 方法是唯一向该属性添加类的方法,它由 JVM 调用。这样,每个 Class 对象至少有一个对它的引用并且没有反射,自定义类加载器无法删除此引用。据我所知,Java 中的想法是强制 GC 仅在卸载首先加载它的类加载器后才卸载该类。
      • (续)我检查了 Tomcat 如何加载类我无法从 ClassLoader 中找到对属性类的引用。所以,我的理解是,一个类实际上一旦被加载就永远不会被卸载。所以,最后,这应该会导致与内存相关的错误。而且我很好奇Tomcat没有到达这里。
      猜你喜欢
      • 2015-10-20
      • 2020-01-09
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多