KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jelly > core > BaseMemoryLeakTest


1 /*
2  * Copyright 2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.jelly.core;
17
18 import java.io.ByteArrayInputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.net.URL JavaDoc;
22
23 import junit.framework.TestCase;
24
25 import org.apache.commons.jelly.JellyContext;
26 import org.apache.commons.jelly.JellyException;
27 import org.apache.commons.jelly.Script;
28 import org.apache.commons.jelly.XMLOutput;
29 import org.apache.commons.jelly.parser.XMLParser;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.xml.sax.InputSource JavaDoc;
33 import org.xml.sax.SAXException JavaDoc;
34
35 /**
36  * Automates the basic process of testing a tag library for a memory leak.
37  * <p>
38  * To use it, extend it. Use the {@link runScriptManyTimes(String, int)}
39  * method in your unit tests.
40  *
41  * @author Hans Gilde
42  *
43  */

44 public class BaseMemoryLeakTest extends TestCase {
45     private final static Log log = LogFactory.getLog(BaseMemoryLeakTest.class);
46
47     /**
48      * The JUnit constructor
49      *
50      * @param name
51      */

52     public BaseMemoryLeakTest(String JavaDoc name) {
53         super(name);
54     }
55
56     /** Runs a script count times and reports the number of bytes "leaked".
57      * Note that "leaked" means "not collected by the GC"
58      * and can easily be different between JVM's. This is because all
59      * freed references may not be available for GC in the short time
60      * between their freeing and the completion of this test.
61      * <p/>
62      * However, running a
63      * script 10,000 or 100,000 times should be a pretty good test
64      * for a memory leak. If there's not too much memory "leaked",
65      * you're probably OK.
66      * @param scriptName The path to the script, from the classloader of the current class.
67      * @param count The number of times to run the script.
68      * @return The number of bytes "leaked"
69      * @throws IOException
70      * @throws SAXException
71      * @throws JellyException
72      */

73     public long runScriptManyTimes(String JavaDoc scriptName, int count)
74             throws IOException JavaDoc, SAXException JavaDoc, JellyException {
75         Runtime JavaDoc rt = Runtime.getRuntime();
76         JellyContext jc = new JellyContext();
77         jc.setClassLoader(getClass().getClassLoader());
78
79         XMLOutput output = XMLOutput.createDummyXMLOutput();
80         
81         URL JavaDoc url = this.getClass().getResource(scriptName);
82
83         String JavaDoc exturl = url.toExternalForm();
84         int lastSlash = exturl.lastIndexOf("/");
85         String JavaDoc extBase = exturl.substring(0,lastSlash+1);
86         URL JavaDoc baseurl = new URL JavaDoc(extBase);
87         jc.setCurrentURL(baseurl);
88         
89         InputStream JavaDoc is = url.openStream();
90         byte[] bytes = new byte[is.available()];
91         is.read(bytes);
92
93         InputStream JavaDoc scriptIStream = new ByteArrayInputStream JavaDoc(bytes);
94         InputSource JavaDoc scriptISource = new InputSource JavaDoc(scriptIStream);
95
96         is.close();
97         is = null;
98         bytes = null;
99
100         rt.runFinalization();
101         rt.gc();
102
103         long start = rt.totalMemory() - rt.freeMemory();
104         log.info("Starting memory test with used memory of " + start);
105
106         XMLParser parser;
107         Script script;
108
109         int outputEveryXIterations = outputEveryXIterations();
110
111         for (int i = 0; i < count; i++) {
112             scriptIStream.reset();
113             parser = new XMLParser();
114
115             script = parser.parse(scriptISource);
116             script.run(jc, output);
117             // PL: I don't see why but removing the clear here
118
// does make the test fail!
119
// As if the WeakHashMap wasn't weak enough...
120

121             //Hans: The structure of the relationship
122
// between TagScript and Tag prevents WeakHashMap
123
// from working in this case, which is why I removed it.
124
jc.clear();
125
126             if (outputEveryXIterations != 0 && i % outputEveryXIterations == 0) {
127                 parser = null;
128                 script = null;
129                 
130                 rt.runFinalization();
131                 rt.gc();
132                 long middle = rt.totalMemory() - rt.freeMemory();
133                 log.info("Memory test after " + i + " runs: "
134                         + (middle - start));
135             }
136         }
137         
138         rt.gc();
139
140         jc = null;
141         output = null;
142         parser = null;
143         script = null;
144
145         scriptIStream = null;
146         scriptISource = null;
147
148         rt.runFinalization();
149         rt.gc();
150         
151         long nullsDone = rt.totalMemory() - rt.freeMemory();
152         log.info("Memory test completed, memory \"leaked\": " + (nullsDone - start));
153         
154         return nullsDone - start;
155     }
156
157     protected int outputEveryXIterations() {
158         return 1000;
159     }
160
161 }
162
Popular Tags