tomcat防cc_浅析Tomcat防止资料被锁的方式

在Windows平台的Tomcat上部署应用后,应用下的个别文件可能会被Tomcat锁住,解部署的时候删除不掉那些内容,就会导致无法重部署。如果解部署删除不掉被锁的文件,Tomcat会在日志中警告说:

2013-1-9 15:44:09 org.apache.catalina.startup.ExpandWar delete

严重: [D:\tomcat\apache-tomcat-7.0.32\webapps\struts2-blank] could not be completely deleted. The presence of the remaining files may cause problems

被锁的文件通常是/WEB-INF/lib下的Jar包,又以Struts2和XWork的Jar包为甚。

遇到这个问题,最简单但最折腾的做法就是停止Tomcat、手动删除webapps目录下残留的文件,再重启、重新部署应用。

56ab0a8d12d2f68b6e703b12378b5d4e.gif

说明:

测试应用是Struts 2.3.8自带的struts2-blank.war

源码分析对象是Tomcat 7.0.23

1. 文件是如何被锁的?

Tomcat会为每个应用创建一个单独的ClassLoader(WebappClassLoader),负责加载应用使用的Java类和资源。

WebappClassLoader是java.net.URLClassLoader的子类,URLClassLoader在加载资源的时候会使用getResource方法去访问资源,如果资源文件在Jar包里,那就会打开到Jar包的URL连接,而URLConnection缺省会打开一个缓存、将创建过连接的内容缓存起来,一旦内容被缓存,那相应的Jar包就会被锁定。

2. 解决方案

针对Windows上文件被锁、不能重部署应用的问题,Tomcat给出了两个解决方案:

2.1 从Tomcat 5.0开始,可以在context.xml的Context元素上设置antiJARLocking属性为true;从Tomcat 5.5开始,可以在context.xml的Context元素上设置antiResourceLocking属性为true(说明)

但在Tomcat 7.0.23(注释掉server.xml里Server元素下的JreMemoryLeakPreventionListener,这个监听器在后面分析)和Tomcat 6.0.20里用struts2-blank.war测试,只有将antiResourceLocking设置为true,Struts和XWork的Jar包才会在解部署时删除。接下来分析一下这两个属性的工作原理。

(1)antiJARLocking

先来看看应用的antiJARLocking属性设置为true时,Tomcat是怎么处理的。

针对antiJARLocking属性的处理集中在WebappClassLoader的getResource和findResourceInternal方法里,主要原理是将包含在Jar包里的资源抽取放到应用的工作目录(work里应用对应的目录)下去。findResourceInternal的主要代码为:

if (antiJARLocking && !(path.endsWith(".class"))) {

byte[] buf = new byte[1024];

File resourceFile = new File

(loaderDir, jarEntry.getName());

if (!resourceFile.exists()) {

Enumeration entries =

jarFiles[i].entries();

while (entries.hasMoreElements()) {

JarEntry jarEntry2 = entries.nextElement();

if (!(jarEntry2.isDirectory())

&& (!jarEntry2.getName().endsWith

(".class"))) {

resourceFile = new File

(loaderDir, jarEntry2.getName());

......

File parentFile = resourceFile.getParentFile();

if (!parentFile.mkdirs() && !parentFile.exists()) {

// Ignore the error (like the IOExceptions below)

}

FileOutputStream os = null;

InputStream is = null;

try {

is = jarFiles[i].getInputStream

(jarEntry2);

os = new FileOutputStream

(resourceFile);

while (true) {

int n = is.read(buf);

if (n <= 0) {

break;

}

os.write(buf, 0, n);

}

resourceFile.setLastModified(

jarEntry2.getTime());

} catch (IOException e) {

// Ignore

} finally {

// 关闭流、释放资源

}

}

}

}

}

把这个属性设置为true之后,部署应用就可以在work\Catalina\localhost\struts2-blank\loader目录下看到被解压的Jar包内容。

antiJARLocking属性在有的时候并不会生效,从WebappClassLoader的getResource和findResource方法逻辑里可以看出一些端倪,在一些情况下(通过对Loader的delegate、searchExternalFirst等相关属性进行配置),资源的获取并不是WebappClassLoader去做的,而是其父加载器的getResource方法或父类的findResource方法去做的,WebappClassLoader的父类是URLClassLoader、父加载器是URLClassLoader实例。

(2)antiResourceLocking

当antiResourceLocking设置为true的时候,Tomcat不会锁定应用下的任何文件。那Tomcat是怎么做到这一点的呢?

在Tomcat的架构里,应用也是一个级别的容器,对应的接口是Context;各级容器本身都具备生命周期,而且配置了多个生命周期监听器来监听容器不同的生命周期过程。Tomcat在初始化的时候,给Context增加了一个生命周期监听器org.apache.catalina.startup.ContextConfig;然后在Context真正开始启动之前,会有一个BEFORE_START_EVENT状态,ContextConfig监听到这个状态的事件后,就会针对antiResourceLocking进行处理。

1119201306.jpg

antiLocking的主要代码和主要逻辑为:

protected void antiLocking() {

// 只针对应用做处理,应用的antiResourceLocking属性设置为true

if ((context instanceof StandardContext)

&& ((StandardContext) context).getAntiResourceLocking()) {

// 获取应用原始的doc base(docBaseFile变量,缺省是webapps下以应用名称为名的目录)

Host host = (Host) context.getParent();

String appBase = host.getAppBase();

String docBase = context.getDocBase();

if (docBase == null)

return;

if (originalDocBase == null) {

originalDocBase = docBase;

} else {

docBase = originalDocBase;

}

File docBaseFile = new File(docBase);

if (!docBaseFile.isAbsolute()) {

File file = new File(appBase);

if (!file.isAbsolute()) {

file = new File(getBaseDir(), appBase);

}

docBaseFile = new File(file, docBase);

}

// 获取应用的“path + version”,作为新的doc base,version通常是空

String path = context.getPath();

if (path == null) {

return;

}

ContextName cn = new ContextName(path, context.getWebappVersion());

docBase = cn.getBaseName();

// 在java.io.tmpdir下新建目录

File file = null;

if (originalDocBase.toLowerCase(Locale.ENGLISH).endsWith(".war")) {

file = new File(System.getProperty("java.io.tmpdir"),

deploymentCount++ + "-" + docBase + ".war");

} else {

file = new File(System.getProperty("java.io.tmpdir"),

deploymentCount++ + "-" + docBase);

}

// 将应用的内容从原始doc base拷贝到java.io.tmpdir下新建的目录中,

// 并将临时目录下的内容作为应用的doc base

ExpandWar.delete(file);

if (ExpandWar.copy(docBaseFile, file)) {

context.setDocBase(file.getAbsolutePath());

}

}

}

总结一下,就是如果应用的antiResourceLocking属性设置为true,就将应用的doc base移到临时目录下,让Tomca不会占用webapps下的文件。Tomcat里java.io.tmpdir默认指向Tomcat的temp目录。

副作用

从上面的分析来看,antiResourceLocking为true有几个副作用:

1) 会延长应用的启动时间,因为多了临时目录的清理和往临时目录拷贝应用内容的操作;

2) 如果不知道这个属性的原理,修改webapps下应用的JSP,那就不会动态重加载到新的页面内容了,因为应用的doc base已经不再在webapps下了;

3) 停止Tomcat的时候,临时目录下实际的doc base会被删掉,代码如下:

protected synchronized void configureStop() {

......

Host host = (Host) context.getParent();

String appBase = host.getAppBase();

String docBase = context.getDocBase();

// originalDocBase变量初始为null,只有antiResourceLocking为true时才会赋值

if ((docBase != null) && (originalDocBase != null)) {

File docBaseFile = new File(docBase);

if (!docBaseFile.isAbsolute()) {

docBaseFile = new File(appBase, docBase);

}

// 删除

ExpandWar.delete(docBaseFile, false);

}

......

}

结合第二条和第三条,如果要修改应用的JSP,那必须将改动同时拷贝到两个目录下(原始doc base和临时目录下的doc base)。

所以Tomcat里这个属性缺省为false。在使用Tomcat 6.0.24之前的版本时,如果要用这个属性解决文件被锁的问题,三思而行。

2.2 从Tomcat 6.0.24开始,可以在server.xml的Server元素下配置JreMemoryLeakPreventionListener的urlCacheProtection属性为true(说明)

这个监听器有诸多属性,其中解决文件被锁的是urlCacheProtection属性。urlCacheProtection的原理很简单,就是针对文件被锁的根本原因进行处理——在Server(Tomcat的顶级容器)初始化之前就将URLConnection的缓存关掉。

// Set the default URL caching policy to not to cache

if (urlCacheProtection) {

try {

// Doesn't matter that this JAR doesn't exist - just as

// long as the URL is well-formed

URL url = new URL("jar:file://dummy.jar!/");

URLConnection uConn = url.openConnection();

uConn.setDefaultUseCaches(false); // 修改URLConnection私有的静态变量defaultUserCaches

} catch (MalformedURLException e) {

log.error(sm.getString("jreLeakListener.jarUrlConnCacheFail"), e);

} catch (IOException e) {

log.error(sm.getString("jreLeakListener.jarUrlConnCacheFail"), e);

}

}

这个监听器是缺省配置的,urlCacheProtection属性也缺省为true,所以从Tomcat 6.0.24开始,文件被锁定的问题就不存在了。

另外需要注意的是,JreMemoryLeakPreventionListener这个监听器只能设置给Server(Tomcat的顶级容器),所以urlCacheProtection设置为true的话,对所有应用都会生效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python怎么发送微信给自己_Python新手教程:Python微信定时自动给【女朋友】发送天气预报...

效果图主要思路1.从wxpy获取好友列表2.创建定时器3.定时器触发函数4.函数执行&#xff0c;遍历好友列表5.好友对象执行带参函数&#xff0c;参数为该好友城市6.函数中请求百度天气接口&#xff0c;得到该好友对应天气数据&#xff0c;解析处理数据&#xff0c;发送天气信息&…

Science子刊带来新遗传证据:早期人类驯化了自己

来源&#xff1a;中国生物技术网在开始驯化狗、猫、绵羊和牛等动物前&#xff0c;人类可能已经有了驯化一种完全不同动物的传统&#xff0c;就是我们人类自己。近日&#xff0c;发表在《Science Advances》上的一项新研究引用从某种程度上反映驯化元素的一种疾病的遗传证据表明…

简单的HTTP协议——《图解http》第二章

2.1 HTTP协议用于客户端和服务端直接的通信 在一条通信线路上必定一端是客户端&#xff0c;另一端则是服务端。 2.2 通过请求和响应的交换达成通信。 HTTP协议规定&#xff0c;请求从客户端发出&#xff0c;最后服务器响应该请求并返回。 请求报文的构成和解读。 请求报文是由请…

nacicat for mysql查询_navicat for mysql怎么用

navicat简单的使用方法&#xff1a;1、创建数据库&#xff1a;选中连接名&#xff0c;右键&#xff0c;点击新建数据库。2、删除数据库&#xff1a;选中要删除的数据库&#xff0c;右键&#xff0c;点击删除数据库。3、创建数据表&#xff1a;双击test01,选中表&#xff0c;右键…

字节跳动开发者工具_FAQ | 字节跳动小游游戏发布常见问题汇总

在说常见问题之前&#xff0c;我们先强调2点字节跳动小游戏的基础技术限制(这个很重要&#xff0c;请认真阅读)&#xff1a;第1&#xff1a;不允许操作 DOM、BOM&#xff0c;必须改成平台相应的 API 调用方式&#xff1b;第2&#xff1a;不允许动态执行代码的能力&#xff0c;e…

人机协同作战:或改写未来战争规则

来源&#xff1a;中国军网人工智能技术的发展&#xff0c;将深刻影响人机协同作战从态势感知、指挥决策、目标引导、火力打击到毁伤评估的全过程。在人工智能技术的推动下&#xff0c;人机协同作战极有可能成为改写未来战争规则的重要手段之一。人工智能为人机协同作战“补齐短…

微信 获取wx.config 参数 基类

微信 获取wx.config 参数 基类 原文:微信 获取wx.config 参数 基类using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Script.Serialization;using System.Text;using System.Web.Caching; namespace Saturn.TTS.WMS.WeiXiP…

mysql的exp平方_MySQL EXP()用法及代码示例

MySQL中的EXP()函数用于将E提升为指定数字的幂。这里E(2.718281 ...)是自然对数的底数。用法:EXP(X)参数&#xff1a;此方法接受语法中上面提到并在下面描述的一个参数&#xff1a;X-一个指定的数字&#xff0c;将用作E的幂。返回值&#xff1a;它返回提高到给定数字X的幂的E。…

激荡十年:美国正在衰落和正在兴起的25个行业

来源&#xff1a;资本实验室 十年&#xff0c;在人类历史中只是非常短暂的一瞬。但是&#xff0c;十年时间又具备了足够的力量&#xff0c;能够对各行业的发展带来剧烈变革。在2009—2018这十年中&#xff0c;以互联网、移动互联网为依托的各种新兴技术层出不穷&#xff0c;不仅…

命令行参数怎么输入_太好用了!谷歌开源的命令行接口工具fire

大家使用最多的命令行工具应该是pip了&#xff0c;pip提供了很多的命令行参数和选项&#xff0c;我们在终端使用pip install --help命令可以查看install子命令的帮助文档。可以看到&#xff0c;除了最常用的pip install package命令&#xff0c;我们还可以附加很多可选选项来控…

Elasticsearch5中安装Elasticsearch-head插件

介绍 elasticsearch-head是一个用于管理Elasticsearch的web前端插件&#xff0c;搞过ES的同学应该都了解。该插件在es5中可以以独立服务的形式进行安装使用。本文将介绍如何操作。 相关链接&#xff1a;https://github.com/mobz/elasticsearch-headhttp://mobz.github.io/elast…

登录mysql一闪而过_解决MySQL 一闪而过的情况

winform中选择文件获取路径private void button1_Click(object sender, EventArgs e) { //此时弹出一个可以选择文件的窗体 OpenFileDialog fileDialog ...SQLite核心函数一览abs(X) abs(X)返回 X 的绝对值. Abs(X) returns NULL if X is NULL. Abs(X) return 0.0 if X is a s…

plsql最多可以存多少_银行内部透露:如果有10万块钱,可以都放在余额宝里吗?存银行是不是更好?...

阅读本文前&#xff0c;请您先点击上面的“蓝色字体”&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到最新文章了。每天都有分享。完全是免费订阅&#xff0c;请放心关注。声明&#xff1a;图文来源于网络&#xff0c;版权归原作者所有&#xff0c; 如有侵权请…

图解未来50年前沿科技趋势与22个预测

任何理论研究&#xff0c;必须具有符合未来发展趋势的预测&#xff0c;才能体现其可能的价值。近15年来&#xff0c;我们深入研究互联网结构的变化&#xff0c;提出在过去50年里&#xff0c;互联网从网状结构进化成为大脑模型是21世纪前沿科技爆发的根源&#xff0c;包括物联网…

centos8安装MySQL依赖_centos8安装mysql8

1&#xff0c;检查是否有mysql残留文件查找出安装的mysql软件包和依赖包rpm -pa | grep mysql依次删除yum remove mysql-xxx-xxx-查找出所用的配置文件find / -name mysql依次删除rm -rf /var/lib/mysql2&#xff0c;删除MariaDB的文件&#xff0c;装MySQL的话会和MariaDB的文件…

java format用法_java学习常用函数之日期时间函数

日期时间函数DATE_FORMAT(datetime ,fmt)和STR_TO_DATE(str, fmt)所需的日期模板使用NOW(),SYSDATE(),CURDATE(),CURTIME()获取当前时间SELECT CURTIME(),CURDATE(),NOW(),SYSDATE();DATEDIFF(date1,date2) 返回两个日期之间相差的天数SELECT DATEDIFF(CURDATE(),’2019-3-1′)…

NeurIPS 2019公布获奖论文!新增杰出新方向奖项,微软华裔研究员斩获经典论文...

来源&#xff1a;大数据文摘备受瞩目的NeurlPS 2019周日一早在温哥华拉开序幕&#xff0c;今天&#xff0c;组委会通过一篇博客公布了包括杰出论文奖、杰出新方向论文奖等五大类奖项。NeurIPS&#xff0c;全称神经信息处理系统大会(Conference and Workshop on Neural Informat…

Adobe Acrobat DC

DC: document cloud 【云服务】 但是Adobe document cloud包括&#xff1a; Acrobat DC, Adobe sign, 以及Web和移动应用程序。 参考&#xff1a; https://acrobat.adobe.com/cn/zh-Hans/acrobat.html https://helpx.adobe.com/cn/document-cloud/faq.html http://tech.163.co…

mongodb和mysql的对比_MongoDB和MySQL的区别

http://www.cnblogs.com/caihuafeng/p/5494336.htmlMongoDB(文档型数据库)&#xff1a;提供可扩展的高性能数据存储一、1、基于分布式文件存储2、高负载情况下添加更多节点&#xff0c;可以保证服务器性能3、将数据存储为一个文档二、比较1、稳定性2、索引&#xff0c;索引放在…

万字长文深度分析华为智能汽车战略

来源&#xff1a; 中信证券2019 年 4 月&#xff0c;华为首次以汽车 Tier1 的身份参加上海车展。2019 年 11 月&#xff0c;北汽新能源总经理郑刚加盟华为。2019 年 11 月&#xff0c;华为发布核心网自动驾驶白皮书。本文为中信证券团队的分析报告&#xff0c;全文超过 15000 字…