If it helps for reference.... Here is our singleton... import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.TransformerFactory; import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactoryConfigurationException;
/** * This class provides a set of methods to obtain a shared instance of various pre-configured XML parser factories. This * is intended to avoid searching the classpath when looking for an implementation of a factory. Using an enumeration to * create a shared instance guarantees a thread-safe singleton since the enumeration itself ensures internally that only * a single instance is available. Each singleton instance is constructed when the enumeration is referenced for the * first time. Configuration of a these factories is not expected to be thread safe; an application programmer should * not allow an instance of this factory to have its setter methods accessed from more than one thread. */ public final class XMLFactory { private enum DocumentBuilderFactorySingleton { SINGLETON; public final DocumentBuilderFactory instance; private DocumentBuilderFactorySingleton() { instance = DocumentBuilderFactory.newInstance(); } } private enum TransformerFactorySingleton { SINGLETON; public final TransformerFactory instance; private TransformerFactorySingleton() { instance = TransformerFactory.newInstance(); } } private enum XPathFactorySingleton { SINGLETON; public final XPathFactory instance; private XPathFactorySingleton() { instance = XPathFactory.newInstance(); } } private XMLFactory() { return; } /** * This method returns a shared instance of a default document builder factory. Do not call any setter methods on * this shared instance. If an alternative configuration is necessary, a new factory should be created. * @return shared instance of document builder factory */ public static final DocumentBuilderFactory getDocumentBuilderFactoryInstance() { return DocumentBuilderFactorySingleton.SINGLETON.instance; } /** * This method returns a new instance of a document builder factory. * @return new instance of document builder factory */ public static final DocumentBuilderFactory newDocumentBuilderFactoryInstance() { return DocumentBuilderFactory.newInstance(getDocumentBuilderFactoryInstance().getClass().getName(), null); } /** * This method returns a shared instance of a default transformer factory. Do not call any setter methods on this * shared instance. If an alternative configuration is necessary, a new factory should be created. * @return shared instance of transformer factory */ public static final TransformerFactory getTransformerFactoryInstance() { return TransformerFactorySingleton.SINGLETON.instance; } /** * This method returns a new instance of a transformer factory. * @return new instance of transformer factory */ public static final TransformerFactory newTransformerFactoryInstance() { return TransformerFactory.newInstance(getTransformerFactoryInstance().getClass().getName(), null); } /** * This method returns a shared instance of a default xpath factory. Do not call any setter methods on this shared * instance. If an alternative configuration is necessary, a new factory should be created. * @return shared instance of xpath factory */ public static final XPathFactory getXPathFactoryInstance() { return XPathFactorySingleton.SINGLETON.instance; } /** * This method returns a new instance of a xpath factory. * @return new instance of xpath factory * @throws XPathFactoryConfigurationException */ public static final XPathFactory newXPathFactoryInstance() throws XPathFactoryConfigurationException { return XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI, getXPathFactoryInstance().getClass().getName(), null); } } -----Original Message----- From: Niall Fitzpatrick <niallfitzpatr...@live.co.uk> Sent: Tuesday, January 14, 2020 11:48 AM To: Tomcat Users List <users@tomcat.apache.org> Subject: Re: Class loader takes long time after server inactivity - Tomcat Version 9.0.10 ________________________________ From: Christopher Schultz <ch...@christopherschultz.net> Sent: 14 January 2020 16:30 To: users@tomcat.apache.org <users@tomcat.apache.org> Subject: Re: Class loader takes long time after server inactivity - Tomcat Version 9.0.10 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Mark, On 1/14/20 9:58 AM, Mark Thomas wrote: > On 14/01/2020 14:40, Niall Fitzpatrick wrote: >> >> >> >> >>> Hi Folks, >>> >>> >>> >>> I have a web application that, after a period of inactivity >>> (1-2hours), will stall for 3 - 35 seconds upon the first new >>> session. All subsequent sessions will not experience this delay >>> unless another period of inactivity occurs. >>> >>> >>> >>> I've found that the delay occurs when loading jars that live in the >>> WEB-INF/lib folder. >>> >>> >>> >>> The issue doesn't occur when the server is first started. Only after >>> a period of 1-2 hours approx. will the next session experience the >>> delay when loading a jar. This leads me to believe that when the >>> server is started 'knowledge' of the jars might be cached, however, >>> after a period of inactivity this cache may expire. The result of >>> this is that the next session after this period causes the lib >>> folder to be searched again which seems to take the 5-35 seconds. >>> >>> >>> >>> My question: Is this theory above correct, and if so, is there a way >>> to configure Tomcat such that this cache doesn't expire so that it >>> doesn't need to be re-populated when a new session begins? >> >> It depends. Which resources are slow to load? >> >> Mark >> >> Hi Mark, > > Thanks for the additional info. That helps a lot. > > Apologies for the following information dump but there are lots of > factors to make you aware of. > >> Doesn't seem to matter which Jar. At first it happened when loading a >> class from my own custom Jar. > > That should be a one-time cost. Once loaded, classes remain in memory > until the web application is stopped. > > Finding the right class can be expensive. The more JARs the > application has, the more expensive the process will be. Tomcat does > cache the list of entries in a JAR for a short period of time to speed > up this search. If the application has been completely idle for a > while then you will see a pause on the first attempt to load a class > while those caches are refreshed. > > Tomcat can't hold the cache for too long as it uses memory and locks > files. > > One possible solution is to use a ServletContextListener and load the > classes you know will be / are likely to be required when the > application starts. > >> I removed this code to determine if it was the cause. However, then I >> found the same problem further downstream. When calling >> DocumentBuilderFactory.newInstance() which lives in >> xml-apis-1.3.04 The delay of 5-35 seconds occurred here instead. > > Ah. That will probably be the biggest culprit. > DocumentBuilderFactory uses an SPI mechanism to find the correct > instance to create. That SPI mechanism involves searching every JAR > for a configuration file. The expectation, although it may not be > documented as clearly as it should, is that > DocumentBuilderFactory.newInstance() is called only once during the > lifetime of a web application and the result cached. +1 But 5-30 seconds is a looong time. Niall, any chance you have a particularly slow disk, loaded server, or maybe a network share where these files are located? - -chris Hi Chris, I don't believe so. A customer reported the issue, and I was able to recreate it on our own test environment. I will say this - the web application has 263 jars in it's lib folder. That's got to be a lot of searching. Thanks for everyone's suggestions. I'm going to try the wrapper class solution where I can cache the result. I'll send an update with what I learned. Niall --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org CONFIDENTIALITY NOTICE This message and any included attachments are from Cerner Corporation and are intended only for the addressee. The information contained in this message is confidential and may constitute inside or non-public information under international, federal, or state securities laws. Unauthorized forwarding, printing, copying, distribution, or use of such information is strictly prohibited and may be unlawful. If you are not the addressee, please promptly delete this message and notify the sender of the delivery error by e-mail or you may call Cerner's corporate offices in Kansas City, Missouri, U.S.A at (+1) (816)221-1024. --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org