json-tck/src/main/java/net/java/html/js/tests/GCBodyTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Fri, 12 Dec 2014 11:22:40 +0100
branchgc
changeset 900 2ee22312e414
parent 894 79574388270b
child 907 dbd7ab3a4714
permissions -rw-r--r--
Giving API users better control over GC aspects of their objects
jaroslav@424
     1
/**
jaroslav@424
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@424
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@424
     5
 *
jaroslav@424
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@424
     7
 * Other names may be trademarks of their respective owners.
jaroslav@424
     8
 *
jaroslav@424
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@424
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@424
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@424
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@424
    13
 * License. You can obtain a copy of the License at
jaroslav@424
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@424
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@424
    16
 * specific language governing permissions and limitations under the
jaroslav@424
    17
 * License.  When distributing the software, include this License Header
jaroslav@424
    18
 * Notice in each file and include the License file at
jaroslav@424
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@424
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@424
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@424
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@424
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@424
    24
 * your own identifying information:
jaroslav@424
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@424
    26
 *
jaroslav@424
    27
 * Contributor(s):
jaroslav@424
    28
 *
jaroslav@424
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@424
    31
 *
jaroslav@424
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@424
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@424
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@424
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@424
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@424
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@424
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@424
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@424
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@424
    41
 * made subject to such option by the copyright holder.
jaroslav@424
    42
 */
jaroslav@424
    43
package net.java.html.js.tests;
jaroslav@424
    44
jtulach@867
    45
import java.lang.ref.Reference;
jtulach@867
    46
import java.lang.ref.WeakReference;
jtulach@838
    47
import org.netbeans.html.json.tck.KOTest;
jaroslav@424
    48
jaroslav@424
    49
/**
jaroslav@424
    50
 *
jtulach@790
    51
 * @author Jaroslav Tulach
jaroslav@424
    52
 */
jtulach@873
    53
public class GCBodyTest {
jtulach@875
    54
    Reference<?> ref;
jtulach@900
    55
    int[] arr;
jtulach@875
    56
    
jtulach@900
    57
    @KOTest public void callbackInterfaceCanDisappear() throws InterruptedException {
jtulach@875
    58
        if (ref != null) {
jtulach@875
    59
            assertGC(ref, "Can disappear!");
jtulach@875
    60
            return;
jtulach@875
    61
        }
jtulach@867
    62
        Sum s = new Sum();
jtulach@867
    63
        int res = Bodies.sumIndirect(s);
jaroslav@424
    64
        assert res == 42 : "Expecting 42";
jtulach@867
    65
        Reference<?> ref = new WeakReference<Object>(s);
jtulach@867
    66
        s = null;
jtulach@867
    67
        assertGC(ref, "Can disappear!");
jaroslav@424
    68
    }
jaroslav@424
    69
    
jtulach@900
    70
    private Object assignInst() {
jtulach@900
    71
        Object obj = Bodies.instance(0);
jtulach@900
    72
        Object s = new EmptyInstance();
jtulach@900
    73
        Bodies.setX(obj, s);
jtulach@900
    74
        assert s == Bodies.readX(obj);
jtulach@900
    75
        ref = new WeakReference<Object>(s);
jtulach@900
    76
        return obj;
jtulach@900
    77
}
jtulach@900
    78
    
jtulach@872
    79
    @KOTest public void holdObjectAndReleaseObject() throws InterruptedException {
jtulach@875
    80
        if (ref != null) {
jtulach@875
    81
            assertGC(ref, "Can disappear!");
jtulach@875
    82
            return;
jtulach@875
    83
        }
jtulach@872
    84
        
jtulach@900
    85
        Object obj = assignInst();
jtulach@900
    86
        assert ref != null;
jtulach@872
    87
        
jtulach@872
    88
        Bodies.setX(obj, null);
jtulach@894
    89
        obj = null;
jtulach@872
    90
        
jtulach@872
    91
        assertGC(ref, "Can disappear!");
jtulach@872
    92
    }
jtulach@900
    93
jtulach@900
    94
    private static Reference<?> sendRunnable(final int[] arr) {
jtulach@900
    95
        Runnable r = new Runnable() {
jtulach@900
    96
            @Override
jtulach@900
    97
            public void run() {
jtulach@900
    98
                arr[0]++;
jtulach@900
    99
            }
jtulach@900
   100
        };
jtulach@900
   101
        Bodies.asyncCallback(r);
jtulach@900
   102
        return new WeakReference<Object>(r);
jtulach@900
   103
    }
jtulach@900
   104
    
jtulach@900
   105
    private static class EmptyInstance {
jtulach@900
   106
    }
jtulach@900
   107
    
jtulach@900
   108
    @KOTest public void parametersNeedToRemainInAsyncMode() throws InterruptedException {
jtulach@900
   109
        if (ref != null) {
jtulach@900
   110
            if (arr[0] != 1) {
jtulach@900
   111
                throw new InterruptedException();
jtulach@900
   112
            }
jtulach@900
   113
            assertGC(ref, "Now the runnable can disappear");
jtulach@900
   114
            return;
jtulach@900
   115
        }
jtulach@900
   116
        arr = new int[] { 0 };
jtulach@900
   117
        ref = sendRunnable(arr);
jtulach@900
   118
        if (arr[0] == 1) {
jtulach@900
   119
            return;
jtulach@900
   120
        }
jtulach@900
   121
        assertNotGC(ref, false, "The runnable should not be GCed");
jtulach@900
   122
        throw new InterruptedException();
jtulach@900
   123
    }
jtulach@872
   124
    
jtulach@867
   125
    private static void assertGC(Reference<?> ref, String msg) throws InterruptedException {
jtulach@893
   126
        for (int i = 0; i < 100; i++) {
jtulach@893
   127
            if (isGone(ref)) return;
jtulach@893
   128
            long then = System.currentTimeMillis();
jtulach@893
   129
            int size = Bodies.gc(Math.pow(2.0, i));
jtulach@893
   130
            long took = System.currentTimeMillis() - then;
jtulach@893
   131
            if (took > 3000) {
jtulach@893
   132
                throw new InterruptedException(msg + " - giving up after " + took + " ms at size of " + size);
jtulach@867
   133
            }
jtulach@893
   134
            
jtulach@867
   135
            try {
jtulach@867
   136
                System.gc();
jtulach@867
   137
                System.runFinalization();
jtulach@867
   138
            } catch (Error err) {
jtulach@867
   139
                err.printStackTrace();
jtulach@867
   140
            }
jtulach@867
   141
        }
jtulach@875
   142
        throw new InterruptedException(msg);
jtulach@867
   143
    }
jtulach@893
   144
jtulach@893
   145
    private static boolean isGone(Reference<?> ref) {
jtulach@893
   146
        return ref.get() == null;
jtulach@893
   147
    }
jtulach@872
   148
    
jtulach@900
   149
    private static void assertNotGC(Reference<?> ref, boolean clearJS, String msg) throws InterruptedException {
jtulach@872
   150
        for (int i = 0; i < 10; i++) {
jtulach@872
   151
            if (ref.get() == null) {
jtulach@872
   152
                throw new IllegalStateException(msg);
jtulach@872
   153
            }
jtulach@900
   154
            if (clearJS) {
jtulach@900
   155
                Bodies.gc(Math.pow(2.0, i));
jtulach@900
   156
            }
jtulach@872
   157
            try {
jtulach@872
   158
                System.gc();
jtulach@872
   159
                System.runFinalization();
jtulach@872
   160
            } catch (Error err) {
jtulach@872
   161
                err.printStackTrace();
jtulach@872
   162
            }
jtulach@872
   163
        }
jtulach@872
   164
    }
jaroslav@424
   165
}