Please use the Apache issue tracking system for new NetBeans issues (https://issues.apache.org/jira/projects/NETBEANS0/issues) !!
View | Details | Raw Unified | Return to bug 206621
Collapse All | Expand All

(-)openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java (+4 lines)
 Lines 1317-1322    Link Here 
1317
    /** Reference to a result R
1317
    /** Reference to a result R
1318
     */
1318
     */
1319
    static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
1319
    static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
1320
        private static final Set<ReferenceToResult<?>> all = new HashSet<ReferenceToResult<?>>();
1320
        /** next refernece in chain, modified only from AbstractLookup or this */
1321
        /** next refernece in chain, modified only from AbstractLookup or this */
1321
        private ReferenceToResult<?> next;
1322
        private ReferenceToResult<?> next;
1322
1323
 Lines 1337-1342    Link Here 
1337
            this.template = template;
1338
            this.template = template;
1338
            this.lookup = lookup;
1339
            this.lookup = lookup;
1339
            getResult().reference = this;
1340
            getResult().reference = this;
1341
            all.add(this);
1340
        }
1342
        }
1341
1343
1342
        /** Returns the result or null
1344
        /** Returns the result or null
 Lines 1348-1355    Link Here 
1348
        /** Cleans the reference. Implements Runnable interface, do not call
1350
        /** Cleans the reference. Implements Runnable interface, do not call
1349
         * directly.
1351
         * directly.
1350
         */
1352
         */
1353
        @Override
1351
        public void run() {
1354
        public void run() {
1352
            lookup.cleanUpResult(this.template);
1355
            lookup.cleanUpResult(this.template);
1356
            all.remove(this);
1353
        }
1357
        }
1354
1358
1355
        /** Clones the reference list to given Storage.
1359
        /** Clones the reference list to given Storage.
(-)openide.util.lookup/src/org/openide/util/lookup/implspi/ActiveQueue.java (+1 lines)
 Lines 124-129    Link Here 
124
                synchronized (this) {
124
                synchronized (this) {
125
                    assert count > 0;
125
                    assert count > 0;
126
                    count--;
126
                    count--;
127
                    LOGGER.info("down to " + count);
127
                    if (count == 0) {
128
                    if (count == 0) {
128
                        // We have processed all we have to process (for now at least).
129
                        // We have processed all we have to process (for now at least).
129
                        // Could be restarted later if ping() called again.
130
                        // Could be restarted later if ping() called again.
(-)openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupPermGenLeakTest.java (+162 lines)
Added Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.openide.util.lookup;
43
44
import java.io.Serializable;
45
import java.lang.ref.Reference;
46
import java.lang.ref.WeakReference;
47
import java.lang.reflect.InvocationHandler;
48
import java.lang.reflect.Method;
49
import java.lang.reflect.Proxy;
50
import java.net.URL;
51
import java.net.URLClassLoader;
52
import java.util.Collection;
53
import java.util.logging.Level;
54
import org.netbeans.junit.NbTestCase;
55
import org.openide.util.Lookup;
56
import org.openide.util.LookupListener;
57
58
/**
59
 *
60
 * @author Jaroslav Tulach <jtulach@netbeans.org>
61
 */
62
public class LookupPermGenLeakTest extends NbTestCase implements InvocationHandler {
63
    private int cnt;
64
65
    public LookupPermGenLeakTest(String name) {
66
        super(name);
67
    }
68
    
69
    protected URLClassLoader createClassLoader() {
70
        URLClassLoader loader;
71
        URL lookup = Lookup.class.getProtectionDomain().getCodeSource().getLocation();
72
        URL tests = LookupPermGenLeakTest.class.getProtectionDomain().getCodeSource().getLocation();
73
        loader = new URLClassLoader(
74
            new URL[] { lookup, tests },
75
            Lookup.class.getClassLoader().getParent()
76
        );
77
        return loader;
78
    }
79
80
    @Override
81
    protected int timeOut() {
82
        return 30000;
83
    }
84
    
85
    @Override
86
    protected Level logLevel() {
87
        return Level.FINE;
88
    }
89
    
90
    private Object createClass() throws Exception {
91
        URLClassLoader loader;
92
        Class<?> classLookup;
93
        Class<?> classLookups;
94
        Class<?> classLookupListener;
95
        Class<?> classLookupResult;
96
        Class<?> classI;
97
        Method methodMetainfServices;
98
        Method methodLookupResult;
99
        Method methodAddLookupListener;
100
        Method methodAllInstances;
101
        
102
        loader = createClassLoader();
103
        
104
        classLookup = loader.loadClass(Lookup.class.getName());
105
        classLookups = loader.loadClass(Lookups.class.getName());
106
        classLookupListener = loader.loadClass(LookupListener.class.getName());
107
        classLookupResult = loader.loadClass(Lookup.Result.class.getName());
108
        classI = loader.loadClass(I.class.getName());
109
        methodMetainfServices = classLookups.getMethod("metaInfServices", ClassLoader.class);
110
        Method methodLookupAll = classLookup.getMethod("lookupAll", Class.class);
111
        methodLookupResult = classLookup.getMethod("lookupResult", Class.class);
112
        methodAddLookupListener = classLookupResult.getMethod("addLookupListener", classLookupListener);
113
        methodAllInstances = classLookupResult.getMethod("allInstances");
114
        Object lkp = methodMetainfServices.invoke(null, loader);
115
        Object res = methodLookupResult.invoke(lkp, Serializable.class);
116
        
117
        Object listener = Proxy.newProxyInstance(loader, new Class[] { classLookupListener }, this);
118
        methodAddLookupListener.invoke(res, listener);
119
        
120
        Collection<?> noneThere = (Collection<?>) methodAllInstances.invoke(res);
121
        assertEquals("There is nothing yet: " + noneThere, 0, noneThere.size());
122
        
123
        methodLookupAll.invoke(lkp, classI);
124
        
125
        Collection<?> oneThere = (Collection<?>) methodAllInstances.invoke(res);
126
        assertEquals("There is one item: " + oneThere, 1, oneThere.size());
127
        
128
        assertEquals("One change", 1, waitForOne());
129
        
130
        return classLookup;
131
    }
132
    
133
    public void testClassLoaderCanGC() throws Exception {
134
        Reference<?> ref = new WeakReference<Object>(createClass());
135
        assertGC("Can be GCed", ref);
136
    }
137
    
138
    private synchronized int waitForOne() throws InterruptedException {
139
        while (cnt != 1) {
140
            wait();
141
        }
142
        return cnt;
143
    }
144
145
    @Override
146
    public synchronized Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
147
        if (method.getName().equals("resultChanged")) { // NOI18N
148
            cnt++;
149
            notifyAll();
150
        }
151
        return null;
152
    }
153
    
154
    
155
    public static interface I {
156
    }
157
    
158
    @ServiceProvider(service=I.class)
159
    public static final class Impl implements I, Serializable {
160
        
161
    }
162
}
(-)openide.util/src/org/openide/util/RequestProcessor.java (-11 / +17 lines)
 Lines 197-205    Link Here 
197
197
198
    /** A shared timer used to pass timed-out tasks to pending queue */
198
    /** A shared timer used to pass timed-out tasks to pending queue */
199
    private static final TickTac TICK = new TickTac();
199
    private static final TickTac TICK = new TickTac();
200
    static {
201
        TICK.start();
202
    }
203
200
204
    /** logger */
201
    /** logger */
205
    private static final Logger logger = Logger.getLogger("org.openide.util.RequestProcessor"); // NOI18N
202
    private static final Logger logger = Logger.getLogger("org.openide.util.RequestProcessor"); // NOI18N
 Lines 1838-1844    Link Here 
1838
        private static final Stack<Processor> pool = new Stack<Processor>();
1835
        private static final Stack<Processor> pool = new Stack<Processor>();
1839
1836
1840
        /* One minute of inactivity and the Thread will die if not assigned */
1837
        /* One minute of inactivity and the Thread will die if not assigned */
1841
        private static final int INACTIVE_TIMEOUT = 60000;
1838
        private static final int INACTIVE_TIMEOUT = 600;
1842
1839
1843
        /** Internal variable holding the Runnable to be run.
1840
        /** Internal variable holding the Runnable to be run.
1844
         * Used for passing Runnable through Thread boundaries.
1841
         * Used for passing Runnable through Thread boundaries.
 Lines 2164-2175    Link Here 
2164
    }
2161
    }
2165
    
2162
    
2166
    private static final class TickTac extends Thread implements Comparator<Item> {
2163
    private static final class TickTac extends Thread implements Comparator<Item> {
2167
        private final PriorityQueue<Item> queue;
2164
        private PriorityQueue<Item> queue;
2168
        
2165
        
2169
        public TickTac() {
2166
        public TickTac() {
2170
            super("RequestProcessor queue manager"); // NOI18N
2167
            super("RequestProcessor queue manager"); // NOI18N
2171
            setDaemon(true);
2168
            setDaemon(true);
2172
            queue = new PriorityQueue<Item>(128, this);
2173
        }
2169
        }
2174
2170
2175
        @Override
2171
        @Override
 Lines 2185-2203    Link Here 
2185
2181
2186
        synchronized final void schedule(Item localItem, long delay) {
2182
        synchronized final void schedule(Item localItem, long delay) {
2187
            localItem.when = System.currentTimeMillis() + delay;
2183
            localItem.when = System.currentTimeMillis() + delay;
2184
            if (queue == null) {
2185
                queue = new PriorityQueue<Item>(128, this);
2186
                start();
2187
            }
2188
            queue.add(localItem);
2188
            queue.add(localItem);
2189
            notifyAll();
2189
            notifyAll();
2190
        }
2190
        }
2191
        
2191
        
2192
        synchronized final void cancel(Item localItem) {
2192
        synchronized final void cancel(Item localItem) {
2193
            queue.remove(localItem);
2193
            if (queue != null) {
2194
                queue.remove(localItem);
2195
                notifyAll();
2196
            }
2194
        }
2197
        }
2195
2198
2196
        @Override
2199
        @Override
2197
        public void run() {
2200
        public void run() {
2198
            for (;;) {
2201
            boolean[] goOn = { true };
2202
            while (goOn[0]) {
2199
                try {
2203
                try {
2200
                    Item first = obtainFirst();
2204
                    Item first = obtainFirst(goOn);
2201
                    if (first != null) {
2205
                    if (first != null) {
2202
                        first.owner.enqueue(first);
2206
                        first.owner.enqueue(first);
2203
                    }
2207
                    }
 Lines 2205-2216    Link Here 
2205
                    continue;
2209
                    continue;
2206
                }
2210
                }
2207
            }
2211
            }
2212
            
2208
        }
2213
        }
2209
        
2214
        
2210
        private synchronized Item obtainFirst() throws InterruptedException {
2215
        private synchronized Item obtainFirst(boolean[] goOn) throws InterruptedException {
2211
            Item first = queue.poll();
2216
            Item first = queue.poll();
2212
            if (first == null) {
2217
            if (first == null) {
2213
                wait();
2218
                queue = null;
2219
                goOn[0] = false;
2214
                return null;
2220
                return null;
2215
            }
2221
            }
2216
            long delay = first.when - System.currentTimeMillis();
2222
            long delay = first.when - System.currentTimeMillis();
(-)openide.util/test/unit/src/org/openide/util/LookupAndRPLeaksPermGenTest.java (+70 lines)
Added Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.openide.util;
43
44
import java.net.URL;
45
import java.net.URLClassLoader;
46
import org.openide.util.lookup.LookupPermGenLeakTest;
47
48
/**
49
 *
50
 * @author Jaroslav Tulach <jtulach@netbeans.org>
51
 */
52
public class LookupAndRPLeaksPermGenTest extends LookupPermGenLeakTest {
53
54
    public LookupAndRPLeaksPermGenTest(String name) {
55
        super(name);
56
    }
57
58
    @Override
59
    protected URLClassLoader createClassLoader() {
60
        URLClassLoader loader;
61
        URL lookup = Lookup.class.getProtectionDomain().getCodeSource().getLocation();
62
        URL rp = RequestProcessor.class.getProtectionDomain().getCodeSource().getLocation();
63
        URL tests = LookupPermGenLeakTest.class.getProtectionDomain().getCodeSource().getLocation();
64
        loader = new URLClassLoader(
65
            new URL[] { lookup, tests, rp },
66
            Lookup.class.getClassLoader().getParent()
67
        );
68
        return loader;
69
    }
70
}

Return to bug 206621
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo