# HG changeset patch # User dholmes # Date 1513123579 18000 # Node ID fe6fb69336b518761e19f31993865c96b069f25d # Parent a576e1b6784d17e8273a414c750ad814fcef28ae 8193222: EnsureLocalCapacity() should maintain capacity requests through multiple calls Reviewed-by: coleenp, dcubed diff -r a576e1b6784d -r fe6fb69336b5 make/test/JtregNativeHotspot.gmk --- a/make/test/JtregNativeHotspot.gmk Tue Dec 12 14:14:06 2017 -0500 +++ b/make/test/JtregNativeHotspot.gmk Tue Dec 12 19:06:19 2017 -0500 @@ -113,6 +113,7 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHandshakeTransitionTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHasNoEntryPoint := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libReturnError := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libTestCheckedEnsureLocalCapacity := -lc endif ifeq ($(OPENJDK_TARGET_OS), linux) diff -r a576e1b6784d -r fe6fb69336b5 src/hotspot/share/prims/jniCheck.cpp --- a/src/hotspot/share/prims/jniCheck.cpp Tue Dec 12 14:14:06 2017 -0500 +++ b/src/hotspot/share/prims/jniCheck.cpp Tue Dec 12 19:06:19 2017 -0500 @@ -826,7 +826,10 @@ } jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity); if (result == JNI_OK) { - add_planned_handle_capacity(thr->active_handles(), capacity); + // increase local ref capacity if needed + if ((size_t)capacity > thr->active_handles()->get_planned_capacity()) { + add_planned_handle_capacity(thr->active_handles(), capacity); + } } functionExit(thr); return result; diff -r a576e1b6784d -r fe6fb69336b5 test/hotspot/jtreg/runtime/jni/checked/TestCheckedEnsureLocalCapacity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/jni/checked/TestCheckedEnsureLocalCapacity.java Tue Dec 12 19:06:19 2017 -0500 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8193222 + * @summary Check EnsureLocalCapacity doesn't shrink unexpectedly + * @library /test/lib + * @run main/othervm/native TestCheckedEnsureLocalCapacity launch + */ +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestCheckedEnsureLocalCapacity { + + static { + System.loadLibrary("TestCheckedEnsureLocalCapacity"); + } + + // Calls EnsureLocalCapacity(capacity) and then creates "copies" number + // of LocalRefs to "o". + // If capacity > copies no warning should ensue (with the bug fixed). + // If copies > capacity + warning-threshold then we still get a warning. + private static native void ensureCapacity(Object o, int capacity, int copies); + + private static int[][] testArgs = { + { 60, 45 }, // good: capacity > copies + { 1, 45 } // bad: copies >> capacity + }; + + private static final String EXCEED_WARNING = + "^WARNING: JNI local refs: \\d++, exceeds capacity:"; + + private static final String WARNING = "^WARNING: "; + + public static void main(String[] args) throws Throwable { + if (args.length == 2) { + ensureCapacity(new Object(), + Integer.parseInt(args[0]), + Integer.parseInt(args[1])); + return; + } + + // No warning + ProcessTools.executeTestJvm("-Xcheck:jni", + "TestCheckedEnsureLocalCapacity", + Integer.toString(testArgs[0][0]), + Integer.toString(testArgs[0][1])). + shouldHaveExitValue(0). + // check no capacity warning + stdoutShouldNotMatch(EXCEED_WARNING). + // check no other warning + stdoutShouldNotMatch(WARNING). + reportDiagnosticSummary(); + + // Warning + ProcessTools.executeTestJvm("-Xcheck:jni", + "TestCheckedEnsureLocalCapacity", + Integer.toString(testArgs[1][0]), + Integer.toString(testArgs[1][1])). + shouldHaveExitValue(0). + // check for capacity warning + stdoutShouldMatch(EXCEED_WARNING). + reportDiagnosticSummary(); + } +} diff -r a576e1b6784d -r fe6fb69336b5 test/hotspot/jtreg/runtime/jni/checked/libTestCheckedEnsureLocalCapacity.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/jni/checked/libTestCheckedEnsureLocalCapacity.c Tue Dec 12 19:06:19 2017 -0500 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +void reduceLocalCapacity(JNIEnv* env) { + puts("reduceLocalCapacity: setting to 1"); + (*env)->EnsureLocalCapacity(env,1); +} + +JNIEXPORT void JNICALL +Java_TestCheckedEnsureLocalCapacity_ensureCapacity(JNIEnv *env, + jobject unused, + jobject target, + jint capacity, + jint copies) { + int i; + printf("ensureCapacity: setting to %d\n", capacity); + (*env)->EnsureLocalCapacity(env, capacity); // set high + reduceLocalCapacity(env); // sets low + + printf("ensureCapacity: creating %d LocalRefs\n", copies); + for (i = 0; i < copies; i++) { + target = (*env)->NewLocalRef(env, target); + } + + puts("ensureCapacity: done"); +}