1/*
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/* @test
25 * @bug 8166188
26 * @requires vm.opt.ExplicitGCInvokesConcurrent != true
27 * @summary Test return of JNI weak global refs from native calls.
28 * @modules java.base
29 * @run main/othervm/native -Xint ReturnJNIWeak
30 * @run main/othervm/native -Xcomp ReturnJNIWeak
31 */
32
33public final class ReturnJNIWeak {
34
35    static {
36        System.loadLibrary("ReturnJNIWeak");
37    }
38
39    private static final class TestObject {
40        public final int value;
41
42        public TestObject(int value) {
43            this.value = value;
44        }
45    }
46
47    private static volatile TestObject testObject = null;
48
49    private static native void registerObject(Object o);
50    private static native void unregisterObject();
51    private static native Object getObject();
52
53    // Create the test object and record it both strongly and weakly.
54    private static void remember(int value) {
55        TestObject o = new TestObject(value);
56        registerObject(o);
57        testObject = o;
58    }
59
60    // Remove both strong and weak references to the current test object.
61    private static void forget() {
62        unregisterObject();
63        testObject = null;
64    }
65
66    // Verify the weakly recorded object
67    private static void checkValue(int value) throws Exception {
68        Object o = getObject();
69        if (o == null) {
70            throw new RuntimeException("Weak reference unexpectedly null");
71        }
72        TestObject t = (TestObject)o;
73        if (t.value != value) {
74            throw new RuntimeException("Incorrect value");
75        }
76    }
77
78    // Verify we can create a weak reference and get it back.
79    private static void testSanity() throws Exception {
80        System.out.println("running testSanity");
81        int value = 5;
82        try {
83            remember(value);
84            checkValue(value);
85        } finally {
86            forget();
87        }
88    }
89
90    // Verify weak ref value survives across collection if strong ref exists.
91    private static void testSurvival() throws Exception {
92        System.out.println("running testSurvival");
93        int value = 10;
94        try {
95            remember(value);
96            checkValue(value);
97            System.gc();
98            // Verify weak ref still has expected value.
99            checkValue(value);
100        } finally {
101            forget();
102        }
103    }
104
105    // Verify weak ref cleared if no strong ref exists.
106    private static void testClear() throws Exception {
107        System.out.println("running testClear");
108        int value = 15;
109        try {
110          remember(value);
111          checkValue(value);
112          // Verify still good.
113          checkValue(value);
114          // Drop reference.
115          testObject = null;
116          System.gc();
117          // Verify weak ref cleared as expected.
118          Object recorded = getObject();
119          if (recorded != null) {
120            throw new RuntimeException("expected clear");
121          }
122        } finally {
123          forget();
124        }
125    }
126
127    public static void main(String[] args) throws Exception {
128        testSanity();
129        testSurvival();
130        testClear();
131    }
132}
133