File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\test\src\main\java\org\jvnet\hudson\test\MemoryAssert.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright 2012 Jesse Glick.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 package org.jvnet.hudson.test;
26
27 import java.lang.ref.WeakReference;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33 import java.util.concurrent.Callable;
34 import jenkins.model.Jenkins;
35 import static org.junit.Assert.*;
36 import org.netbeans.insane.scanner.CountingVisitor;
37 import org.netbeans.insane.scanner.Filter;
38 import org.netbeans.insane.scanner.ScannerUtils;
39
40 /**
41 * Static utility methods for verifying heap memory usage.
42 * Uses the <a href="http://performance.netbeans.org/insane/">INSANE library</a>
43 * to traverse the heap from within your test.
44 * <p>Object sizes are in an idealized JVM in which pointers are 4 bytes
45 * (realistic even for modern 64-bit JVMs in which {@code -XX:+UseCompressedOops} is the default)
46 * but objects are aligned on 8-byte boundaries (so dropping an {@code int} field does not always save memory).
47 * <p>{@code import static org.jvnet.hudson.test.MemoryAssert.*;} to use.
48 */
49 public class MemoryAssert {
50
51 private MemoryAssert() {}
52
53 /**
54 * Verifies that an object and its transitive reference graph occupy at most a predetermined amount of memory.
55 * The referents of {@link WeakReference} and the like are ignored.
56 * <p>To use, run your test for the first time with {@code max} of {@code 0};
57 * when it fails, use the reported actual size as your assertion maximum.
58 * When improving memory usage, run again with {@code 0} and tighten the test to both demonstrate
59 * your improvement quantitatively and prevent regressions.
60 * @param o the object to measure
61 * @param max the maximum desired memory usage (in bytes)
62 */
63 public static void assertHeapUsage(Object o, int max) throws Exception {
64 // XXX could use ScannerUtils.recursiveSizeOf here
65 CountingVisitor v = new CountingVisitor();
66 ScannerUtils.scan(ScannerUtils.skipNonStrongReferencesFilter(), v, Collections.singleton(o), false);
67 int memoryUsage = v.getTotalSize();
68 assertTrue(o + " consumes " + memoryUsage + " bytes of heap, " + (memoryUsage - max) + " over the limit of " + max, memoryUsage <= max);
69 }
70
71 /**
72 * @see #increasedMemory
73 * @since 1.500
74 */
75 public static final class HistogramElement implements Comparable<HistogramElement> {
76 public final String className;
77 public final int instanceCount;
78 public final int byteSize;
79 HistogramElement(String className, int instanceCount, int byteSize) {
80 this.className = className;
81 this.instanceCount = instanceCount;
82 this.byteSize = byteSize;
83 }
84 @Override public int compareTo(HistogramElement o) {
85 int r = o.byteSize - byteSize;
86 return r != 0 ? r : className.compareTo(o.className);
87 }
88 @Override public boolean equals(Object obj) {
89 if (!(obj instanceof HistogramElement)) {
90 return false;
91 }
92 HistogramElement o = (HistogramElement) obj;
93 return o.className.equals(className);
94 }
95 @Override public int hashCode() {
96 return className.hashCode();
97 }
98 }
99
100 /**
101 * Counts how much more memory is held in Jenkins by doing some operation.
102 * @param callable an action
103 * @param filters things to exclude
104 * @return a histogram of the heap delta after running the operation
105 * @since 1.500
106 */
107 public static List<HistogramElement> increasedMemory(Callable<Void> callable, Filter... filters) throws Exception {
108 Filter f = ScannerUtils.skipNonStrongReferencesFilter();
109 if (filters.length > 0) {
110 Filter[] fs = new Filter[filters.length + 1];
111 fs[0] = f;
112 System.arraycopy(filters, 0, fs, 1, filters.length);
113 f = ScannerUtils.compoundFilter(fs);
114 }
115 CountingVisitor v1 = new CountingVisitor();
116 ScannerUtils.scan(f, v1, Collections.singleton(Jenkins.getInstance()), false);
117 Set<Class<?>> old = v1.getClasses();
118 callable.call();
119 CountingVisitor v2 = new CountingVisitor();
120 ScannerUtils.scan(f, v2, Collections.singleton(Jenkins.getInstance()), false);
121 List<HistogramElement> elements = new ArrayList<HistogramElement>();
122 for (Class<?> c : v2.getClasses()) {
123 int delta = v2.getCountForClass(c) - (old.contains(c) ? v1.getCountForClass(c) : 0);
124 if (delta > 0) {
125 elements.add(new HistogramElement(c.getName(), delta, v2.getSizeForClass(c) - (old.contains(c) ? v1.getSizeForClass(c) : 0)));
126 }
127 }
128 Collections.sort(elements);
129 return elements;
130 }
131
132 /**
133 * Forces GC by causing an OOM and then verifies the given {@link WeakReference} has been garbage collected.
134 * @param reference object used to verify garbage collection.
135 */
136 public static void assertGC(WeakReference<?> reference) {
137 assertTrue(true); reference.get(); // preload any needed classes!
138 Set<Object[]> objects = new HashSet<Object[]>();
139 while (true) {
140 try {
141 objects.add(new Object[1024]);
142 } catch (OutOfMemoryError ignore) {
143 break;
144 }
145 }
146 assertTrue(reference.get() == null);
147 }
148
149 }
150