Return-Path: X-Original-To: apmail-tomcat-users-archive@www.apache.org Delivered-To: apmail-tomcat-users-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 35F3910A9B for ; Tue, 16 Jul 2013 22:53:10 +0000 (UTC) Received: (qmail 47682 invoked by uid 500); 16 Jul 2013 22:53:06 -0000 Delivered-To: apmail-tomcat-users-archive@tomcat.apache.org Received: (qmail 47625 invoked by uid 500); 16 Jul 2013 22:53:06 -0000 Mailing-List: contact users-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Users List" Delivered-To: mailing list users@tomcat.apache.org Received: (qmail 47616 invoked by uid 99); 16 Jul 2013 22:53:06 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 16 Jul 2013 22:53:06 +0000 X-ASF-Spam-Status: No, hits=-0.0 required=5.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of aw@ice-sa.com designates 212.85.38.228 as permitted sender) Received: from [212.85.38.228] (HELO tor.combios.es) (212.85.38.228) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 16 Jul 2013 22:53:00 +0000 Received: from [192.168.245.200] (montserrat.wissensbank.com [212.85.37.175]) (Authenticated sender: andre.warnier@ice-sa.com) by tor.combios.es (Postfix) with ESMTPA id BB6633C0119 for ; Wed, 17 Jul 2013 00:53:04 +0200 (CEST) Message-ID: <51E5CEAE.5000802@ice-sa.com> Date: Wed, 17 Jul 2013 00:52:30 +0200 From: =?ISO-8859-1?Q?Andr=E9_Warnier?= Reply-To: Tomcat Users List User-Agent: Thunderbird 2.0.0.24 (Windows/20100228) MIME-Version: 1.0 To: Tomcat Users List Subject: Re: [OT] Cannot cleanly undeploy a web application References: <51E5BE91.8010800@yahoo.com> In-Reply-To: <51E5BE91.8010800@yahoo.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Checked: Checked by ClamAV on apache.org Mark Eggers wrote: > Folks, > > Off topic, so I'm going to be burning a little karma (OK, a lot). > > Environment: > > Window 7 64 bit > JRE 1.7.0_25 > Tomcat 7.0.42 (with tcnative) run from startup.bat > > I have a web application that scans for a resource path using: > > this.getClass().getClassLoader().getResources(resourcePath) > > It then wanders through the resources, checking the protocol for each > URL in the returned enumeration. > > Based on the protocol, the URL is scanned for desired information and > the names of those resources are collected. > > For a JAR file, I use the following code (don't shoot me - I'm an admin > / architect, not a developer). > > public ArrayList getResources(String resourcePath, > String ending) { > JarURLConnection urlCon = null; > Pattern p = > Pattern.compile("^" + resourcePath + "/.+(" + ending + ")$"); > try { > urlCon = (JarURLConnection) url.openConnection(); > urlCon.setUseCaches(false); > JarFile jar = urlCon.getJarFile(); > Enumeration je = jar.entries(); > while (je.hasMoreElements()) { > String entry = je.nextElement().getName(); > if (log.isDebugEnabled()) { > log.debug("JAR entry: " + entry); > } > Matcher m = p.matcher(entry); > if (m.matches()) { > resources.add(entry); > } > } > } catch (IOException ex) { > resources.add("Could not open resource"); > if (log.isErrorEnabled()) { > log.error("Could not open resource",ex); > } > } finally { > if (null != urlCon) { > urlCon = null; > } > } > return this.resources; > } > > Finally, > > this.getClass().getClassLoader().getResourceAsStream() > > is used to obtain the resources, process them, and stuff them into a > HashMap managed by a singleton. > > This is all done via a servlet context listener, and the HashMap is > emptied in the listener's contextDestroyed method. > > On Linux, this all works well. I can deploy and undeploy with abandon. > The Tomcat manager reports no leaks. > > On Windows, I cannot cleanly undeploy. The JAR files containing the > resourcePath (and hence the resources) remain in > %CATALINA_HOME%\webapps\appname. > > However, once even a minor garbage collection occurs I can then cleanly > undeploy the web application. > > I have several solutions: > > 1. context.xml antiResourceLocking="true" > > This works, but there are a lot of downsides ( noted in the > documentation). This also indicates that an underlying InputStream is > being held open when parsing the JAR file. The solution is also Tomcat - > specific. > > 2. Never package the desired resources in a JAR > > This works, but developers may balk. Also, the path to the desired > resources must be unique, otherwise you could still trigger loading from > a JAR (although I could just not handle JAR scanning). > > 3. Copy the JAR file to java.io.tmpdir, extract, and read > > This is ugly, but might work. It would impact the application start up > time even more, but the JAR scanning issue would no longer exist. I > think Glassfish does this. > > 4. Use a properties file > > Read in a properties file with a list of desired resources, and use that > list to populate the singleton. This is actually what I had in place > before, but this then requires developers to manage both the resources > and the list. > > This solution also makes developing a modular, platform-independent > build system more difficult (it can be done, just creates an extra step > using Maven). Right now the build is a convoluted Ant script that > requires a specific environment. I'm trying to get away from that. > > 5. Do this right > > How, I'm not exactly sure. Hence, the question. > I'll go a bit on a limb here, so someone may shoot me too and you won't be alone. (*) It's also [OT][OT], just to provide some background information. I believe that the underlying issue here is the difference in behaviour between Windows and Unix/Linux, with regard to a file opened by one process, when another process tries to delete the file. Unix/Linux allow this. The file entry in the directory is deleted, the process deleting it gets no error. The file itself is not deleted, and the process which has it open still has a handle to the file and can continue to access it. Under Windows however, the process trying to delete the file gets an error, at the very moment of the "delete". What probably happens here, is that one level below the InputStream which holds the filehandle in Java, is some native file object which has the file open. The InputStream object is discarded at tbe Java level, but is only really destroyed at the next GC. In the meantime, the underlying native object still holds the file. When the GC happens, the underlying filehandle is closed, and everyone is happy. (*) I don't see why they would though. I'm pretty impressed by your admin/architect code above, and wish I was as fluent in Java as you seem to be. --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org For additional commands, e-mail: users-help@tomcat.apache.org