Apache Commons의 dbcp의 테스트코드에서 OOME 테스트 코드가 있어서 공유한다.
http://svn.apache.org/viewvc/commons/proper/pool/branches/POOL_1_X/src/test/org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java?view=markup&pathrev=1084639
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more |
3 | * contributor license agreements. See the NOTICE file distributed with |
4 | * this work for additional information regarding copyright ownership. |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 |
6 | * (the "License"); you may not use this file except in compliance with |
7 | * the License. You may obtain a copy of the License at |
8 | * |
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing permissions and |
15 | * limitations under the License. |
16 | */ |
17 | |
18 | package org.apache.commons.pool.impl; |
19 | |
20 | import java.util.Arrays; |
21 | import java.util.LinkedList; |
22 | import java.util.List; |
23 | |
24 | import junit.framework.TestCase; |
25 | |
26 | import org.apache.commons.pool.BasePoolableObjectFactory; |
27 | import org.apache.commons.pool.PoolableObjectFactory; |
28 | |
29 | /** |
30 | * @author Dirk Verbeeck |
31 | * @author Sandy McArthur |
32 | * @version $Revision$ $Date$ |
33 | */ |
34 | public class TestSoftRefOutOfMemory extends TestCase { |
35 | private SoftReferenceObjectPool pool; |
36 | |
37 | public TestSoftRefOutOfMemory(String testName) { |
38 | super(testName); |
39 | } |
40 | |
41 | public void tearDown() throws Exception { |
42 | if (pool != null) { |
43 | pool.close(); |
44 | pool = null; |
45 | } |
46 | System.gc(); |
47 | } |
48 | |
49 | public void testOutOfMemory() throws Exception { |
50 | pool = new SoftReferenceObjectPool(new SmallPoolableObjectFactory()); |
51 | |
52 | Object obj = pool.borrowObject(); |
53 | assertEquals("1", obj); |
54 | pool.returnObject(obj); |
55 | obj = null; |
56 | |
57 | assertEquals(1, pool.getNumIdle()); |
58 | |
59 | final List garbage = new LinkedList(); |
60 | final Runtime runtime = Runtime.getRuntime(); |
61 | while (pool.getNumIdle() > 0) { |
62 | try { |
63 | long freeMemory = runtime.freeMemory(); |
64 | if (freeMemory > Integer.MAX_VALUE) { |
65 | freeMemory = Integer.MAX_VALUE; |
66 | } |
67 | garbage.add(new byte[Math.min(1024 * 1024, (int)freeMemory/2)]); |
68 | } catch (OutOfMemoryError oome) { |
69 | System.gc(); |
70 | } |
71 | System.gc(); |
72 | } |
73 | garbage.clear(); |
74 | System.gc(); |
75 | |
76 | obj = pool.borrowObject(); |
77 | assertEquals("2", obj); |
78 | pool.returnObject(obj); |
79 | obj = null; |
80 | |
81 | assertEquals(1, pool.getNumIdle()); |
82 | } |
83 | |
84 | public void testOutOfMemory1000() throws Exception { |
85 | pool = new SoftReferenceObjectPool(new SmallPoolableObjectFactory()); |
86 | |
87 | for (int i = 0 ; i < 1000 ; i++) { |
88 | pool.addObject(); |
89 | } |
90 | |
91 | Object obj = pool.borrowObject(); |
92 | assertEquals("1000", obj); |
93 | pool.returnObject(obj); |
94 | obj = null; |
95 | |
96 | assertEquals(1000, pool.getNumIdle()); |
97 | |
98 | final List garbage = new LinkedList(); |
99 | final Runtime runtime = Runtime.getRuntime(); |
100 | while (pool.getNumIdle() > 0) { |
101 | try { |
102 | long freeMemory = runtime.freeMemory(); |
103 | if (freeMemory > Integer.MAX_VALUE) { |
104 | freeMemory = Integer.MAX_VALUE; |
105 | } |
106 | garbage.add(new byte[Math.min(1024 * 1024, (int)freeMemory/2)]); |
107 | } catch (OutOfMemoryError oome) { |
108 | System.gc(); |
109 | } |
110 | System.gc(); |
111 | } |
112 | garbage.clear(); |
113 | System.gc(); |
114 | |
115 | obj = pool.borrowObject(); |
116 | assertEquals("1001", obj); |
117 | pool.returnObject(obj); |
118 | obj = null; |
119 | |
120 | assertEquals(1, pool.getNumIdle()); |
121 | } |
122 | |
123 | public void testOutOfMemoryLarge() throws Exception { |
124 | pool = new SoftReferenceObjectPool(new LargePoolableObjectFactory(1000000)); |
125 | |
126 | Object obj = pool.borrowObject(); |
127 | assertTrue(((String)obj).startsWith("1.")); |
128 | pool.returnObject(obj); |
129 | obj = null; |
130 | |
131 | assertEquals(1, pool.getNumIdle()); |
132 | |
133 | final List garbage = new LinkedList(); |
134 | final Runtime runtime = Runtime.getRuntime(); |
135 | while (pool.getNumIdle() > 0) { |
136 | try { |
137 | long freeMemory = runtime.freeMemory(); |
138 | if (freeMemory > Integer.MAX_VALUE) { |
139 | freeMemory = Integer.MAX_VALUE; |
140 | } |
141 | garbage.add(new byte[Math.min(1024 * 1024, (int)freeMemory/2)]); |
142 | } catch (OutOfMemoryError oome) { |
143 | System.gc(); |
144 | } |
145 | System.gc(); |
146 | } |
147 | garbage.clear(); |
148 | System.gc(); |
149 | |
150 | obj = pool.borrowObject(); |
151 | assertTrue(((String)obj).startsWith("2.")); |
152 | pool.returnObject(obj); |
153 | obj = null; |
154 | |
155 | assertEquals(1, pool.getNumIdle()); |
156 | } |
157 | |
158 | /** |
159 | * Makes sure an {@link OutOfMemoryError} isn't swallowed. |
160 | */ |
161 | public void testOutOfMemoryError() throws Exception { |
162 | pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() { |
163 | public Object makeObject() throws Exception { |
164 | throw new OutOfMemoryError(); |
165 | } |
166 | }); |
167 | |
168 | try { |
169 | pool.borrowObject(); |
170 | fail("Expected out of memory."); |
171 | } |
172 | catch (OutOfMemoryError ex) { |
173 | // expected |
174 | } |
175 | pool.close(); |
176 | |
177 | pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() { |
178 | public Object makeObject() throws Exception { |
179 | return new Object(); |
180 | } |
181 | |
182 | public boolean validateObject(Object obj) { |
183 | throw new OutOfMemoryError(); |
184 | } |
185 | }); |
186 | |
187 | try { |
188 | pool.borrowObject(); |
189 | fail("Expected out of memory."); |
190 | } |
191 | catch (OutOfMemoryError ex) { |
192 | // expected |
193 | } |
194 | pool.close(); |
195 | |
196 | pool = new SoftReferenceObjectPool(new BasePoolableObjectFactory() { |
197 | public Object makeObject() throws Exception { |
198 | return new Object(); |
199 | } |
200 | |
201 | public boolean validateObject(Object obj) { |
202 | throw new IllegalAccessError(); |
203 | } |
204 | |
205 | public void destroyObject(Object obj) throws Exception { |
206 | throw new OutOfMemoryError(); |
207 | } |
208 | }); |
209 | |
210 | try { |
211 | pool.borrowObject(); |
212 | fail("Expected out of memory."); |
213 | } |
214 | catch (OutOfMemoryError ex) { |
215 | // expected |
216 | } |
217 | pool.close(); |
218 | |
219 | } |
220 | |
221 | |
222 | public static class SmallPoolableObjectFactory implements PoolableObjectFactory { |
223 | private int counter = 0; |
224 | |
225 | public Object makeObject() { |
226 | counter++; |
227 | // It seems that as of Java 1.4 String.valueOf may return an |
228 | // intern()'ed String this may cause problems when the tests |
229 | // depend on the returned object to be eventually garbaged |
230 | // collected. Either way, making sure a new String instance |
231 | // is returned eliminated false failures. |
232 | return new String(String.valueOf(counter)); |
233 | } |
234 | public boolean validateObject(Object obj) { |
235 | return true; |
236 | } |
237 | public void activateObject(Object obj) { } |
238 | public void passivateObject(Object obj) { } |
239 | public void destroyObject(Object obj) { } |
240 | } |
241 | |
242 | public static class LargePoolableObjectFactory implements PoolableObjectFactory { |
243 | private String buffer; |
244 | private int counter = 0; |
245 | |
246 | public LargePoolableObjectFactory(int size) { |
247 | char[] data = new char[size]; |
248 | Arrays.fill(data, '.'); |
249 | buffer = new String(data); |
250 | } |
251 | |
252 | public Object makeObject() { |
253 | counter++; |
254 | return String.valueOf(counter) + buffer; |
255 | } |
256 | public boolean validateObject(Object obj) { |
257 | return true; |
258 | } |
259 | public void activateObject(Object obj) { } |
260 | public void passivateObject(Object obj) { } |
261 | public void destroyObject(Object obj) { } |
262 | } |
263 | } |
'java core' 카테고리의 다른 글
jdk 1.6 update 18 이하 버전에 gc 이슈가 있음 (0) | 2011.06.02 |
---|---|
java에서 dns 캐쉬하도록 지정하기 (0) | 2011.03.25 |
jps, jstat 정상작동 (jdk 6u 23부터) 하지만, 톰캣에서 이슈 발생이 됨, jdk update 25기다려야 할 듯 (0) | 2011.02.23 |
java snapshot 사용해보기 (0) | 2011.02.23 |
jdk 6 update 24 중요 설치 (0) | 2011.02.22 |