mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8297106: Remove the -Xcheck:jni local reference capacity checking
Reviewed-by: dcubed, kevinw
This commit is contained in:
parent
05128c2110
commit
692bedbc1d
8 changed files with 1 additions and 289 deletions
|
@ -46,9 +46,6 @@
|
||||||
#include "utilities/formatBuffer.hpp"
|
#include "utilities/formatBuffer.hpp"
|
||||||
#include "utilities/utf8.hpp"
|
#include "utilities/utf8.hpp"
|
||||||
|
|
||||||
// Complain every extra number of unplanned local refs
|
|
||||||
#define CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD 32
|
|
||||||
|
|
||||||
// Heap objects are allowed to be directly referenced only in VM code,
|
// Heap objects are allowed to be directly referenced only in VM code,
|
||||||
// not in native code.
|
// not in native code.
|
||||||
|
|
||||||
|
@ -202,17 +199,6 @@ check_pending_exception(JavaThread* thr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add to the planned number of handles. I.e. plus current live & warning threshold
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
add_planned_handle_capacity(JNIHandleBlock* handles, size_t capacity) {
|
|
||||||
handles->set_planned_capacity(capacity +
|
|
||||||
handles->get_number_of_live_handles() +
|
|
||||||
CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
functionEnterCritical(JavaThread* thr)
|
functionEnterCritical(JavaThread* thr)
|
||||||
{
|
{
|
||||||
|
@ -244,18 +230,7 @@ functionEnterExceptionAllowed(JavaThread* thr)
|
||||||
static inline void
|
static inline void
|
||||||
functionExit(JavaThread* thr)
|
functionExit(JavaThread* thr)
|
||||||
{
|
{
|
||||||
JNIHandleBlock* handles = thr->active_handles();
|
// No checks at this time
|
||||||
size_t planned_capacity = handles->get_planned_capacity();
|
|
||||||
size_t live_handles = handles->get_number_of_live_handles();
|
|
||||||
if (live_handles > planned_capacity) {
|
|
||||||
IN_VM(
|
|
||||||
tty->print_cr("WARNING: JNI local refs: " SIZE_FORMAT ", exceeds capacity: " SIZE_FORMAT,
|
|
||||||
live_handles, planned_capacity);
|
|
||||||
thr->print_stack();
|
|
||||||
)
|
|
||||||
// Complain just the once, reset to current + warn threshold
|
|
||||||
add_planned_handle_capacity(handles, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -746,9 +721,6 @@ JNI_ENTRY_CHECKED(jint,
|
||||||
if (capacity < 0)
|
if (capacity < 0)
|
||||||
NativeReportJNIFatalError(thr, "negative capacity");
|
NativeReportJNIFatalError(thr, "negative capacity");
|
||||||
jint result = UNCHECKED()->PushLocalFrame(env, capacity);
|
jint result = UNCHECKED()->PushLocalFrame(env, capacity);
|
||||||
if (result == JNI_OK) {
|
|
||||||
add_planned_handle_capacity(thr->active_handles(), capacity);
|
|
||||||
}
|
|
||||||
functionExit(thr);
|
functionExit(thr);
|
||||||
return result;
|
return result;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
@ -850,12 +822,6 @@ JNI_ENTRY_CHECKED(jint,
|
||||||
NativeReportJNIFatalError(thr, "negative capacity");
|
NativeReportJNIFatalError(thr, "negative capacity");
|
||||||
}
|
}
|
||||||
jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity);
|
jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity);
|
||||||
if (result == JNI_OK) {
|
|
||||||
// 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);
|
functionExit(thr);
|
||||||
return result;
|
return result;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
|
@ -356,7 +356,6 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(JavaThread* thread, AllocFailType
|
||||||
block->_top = 0;
|
block->_top = 0;
|
||||||
block->_next = NULL;
|
block->_next = NULL;
|
||||||
block->_pop_frame_link = NULL;
|
block->_pop_frame_link = NULL;
|
||||||
block->_planned_capacity = block_size_in_oops;
|
|
||||||
// _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
|
// _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
|
||||||
debug_only(block->_last = NULL);
|
debug_only(block->_last = NULL);
|
||||||
debug_only(block->_free_list = NULL);
|
debug_only(block->_free_list = NULL);
|
||||||
|
@ -550,22 +549,6 @@ size_t JNIHandleBlock::length() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CountJNIHandleClosure: public OopClosure {
|
|
||||||
private:
|
|
||||||
int _count;
|
|
||||||
public:
|
|
||||||
CountJNIHandleClosure(): _count(0) {}
|
|
||||||
virtual void do_oop(oop* ooph) { _count++; }
|
|
||||||
virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); }
|
|
||||||
int count() { return _count; }
|
|
||||||
};
|
|
||||||
|
|
||||||
const size_t JNIHandleBlock::get_number_of_live_handles() {
|
|
||||||
CountJNIHandleClosure counter;
|
|
||||||
oops_do(&counter);
|
|
||||||
return counter.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method is not thread-safe, i.e., must be called while holding a lock on the
|
// This method is not thread-safe, i.e., must be called while holding a lock on the
|
||||||
// structure.
|
// structure.
|
||||||
size_t JNIHandleBlock::memory_usage() const {
|
size_t JNIHandleBlock::memory_usage() const {
|
||||||
|
|
|
@ -147,8 +147,6 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
|
||||||
JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call
|
JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call
|
||||||
uintptr_t* _free_list; // Handle free list
|
uintptr_t* _free_list; // Handle free list
|
||||||
|
|
||||||
// Check JNI, "planned capacity" for current frame (or push/ensure)
|
|
||||||
size_t _planned_capacity;
|
|
||||||
static int _blocks_allocated; // For debugging/printing
|
static int _blocks_allocated; // For debugging/printing
|
||||||
|
|
||||||
// Fill block with bad_handle values
|
// Fill block with bad_handle values
|
||||||
|
@ -179,11 +177,6 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
|
||||||
// Traversal of handles
|
// Traversal of handles
|
||||||
void oops_do(OopClosure* f);
|
void oops_do(OopClosure* f);
|
||||||
|
|
||||||
// Checked JNI support
|
|
||||||
void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; }
|
|
||||||
const size_t get_planned_capacity() { return _planned_capacity; }
|
|
||||||
const size_t get_number_of_live_handles();
|
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle
|
bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle
|
||||||
bool contains(jobject handle) const; // Does this block contain handle
|
bool contains(jobject handle) const; // Does this block contain handle
|
||||||
|
|
|
@ -816,10 +816,6 @@ A JNI call was made without checking for a pending exception from a
|
||||||
previous JNI call, and the current call is not safe when an exception
|
previous JNI call, and the current call is not safe when an exception
|
||||||
may be pending.
|
may be pending.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
The number of JNI local references existing when a JNI function
|
|
||||||
terminates exceeds the number guaranteed to be available.
|
|
||||||
See the \f[V]EnsureLocalcapacity\f[R] function.
|
|
||||||
.IP \[bu] 2
|
|
||||||
A class descriptor is in decorated format (\f[V]Lname;\f[R]) when it
|
A class descriptor is in decorated format (\f[V]Lname;\f[R]) when it
|
||||||
should not be.
|
should not be.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, 2021, 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/native TestCheckedEnsureLocalCapacity launch
|
|
||||||
*/
|
|
||||||
import jdk.test.lib.Utils;
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
// Patterns EXCEED_WARNING and WARNING are not anchored to the beginning
|
|
||||||
// of lines to allow matching interleaved output.
|
|
||||||
|
|
||||||
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",
|
|
||||||
"-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
|
|
||||||
"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",
|
|
||||||
"-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
|
|
||||||
"TestCheckedEnsureLocalCapacity",
|
|
||||||
Integer.toString(testArgs[1][0]),
|
|
||||||
Integer.toString(testArgs[1][1])).
|
|
||||||
shouldHaveExitValue(0).
|
|
||||||
// check for capacity warning
|
|
||||||
stdoutShouldMatch(EXCEED_WARNING).
|
|
||||||
reportDiagnosticSummary();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 <jni.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
|
@ -690,7 +690,6 @@ sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8265770 macosx-all
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
# core_svc
|
# core_svc
|
||||||
tools/launcher/TestXcheckJNIWarnings.java#jdwp-agent 8296936 generic-all
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2021, Red Hat, Inc.
|
|
||||||
* 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 8258836
|
|
||||||
* @summary JNI local refs exceed capacity getDiagnosticCommandInfo
|
|
||||||
* @library /test/lib
|
|
||||||
* @run main/othervm DcmdMBeanTestCheckJni
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import javax.management.MBeanServer;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
import javax.management.remote.JMXConnectorFactory;
|
|
||||||
import javax.management.remote.JMXConnector;
|
|
||||||
import javax.management.remote.JMXConnectorServerFactory;
|
|
||||||
import javax.management.remote.JMXServiceURL;
|
|
||||||
import javax.management.remote.JMXConnectorServer;
|
|
||||||
|
|
||||||
import jdk.test.lib.process.OutputAnalyzer;
|
|
||||||
import jdk.test.lib.process.ProcessTools;
|
|
||||||
|
|
||||||
public class DcmdMBeanTestCheckJni {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
OutputAnalyzer out = ProcessTools.executeTestJvm(
|
|
||||||
"-Xcheck:jni",
|
|
||||||
DcmdMBeanRunner.class.getName());
|
|
||||||
out.shouldNotMatch("WARNING: JNI local refs: \\d+, exceeds capacity: \\d+\\s+" +
|
|
||||||
"at com.sun.management.internal.DiagnosticCommandImpl.getDiagnosticCommandInfo")
|
|
||||||
.shouldContain("DcmdMBeanRunner COMPLETE")
|
|
||||||
.shouldHaveExitValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class DcmdMBeanRunner {
|
|
||||||
|
|
||||||
private static final String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
|
|
||||||
"com.sun.management:type=DiagnosticCommand";
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
|
||||||
JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
|
|
||||||
JMXConnectorServer cs = null;
|
|
||||||
JMXConnector cc = null;
|
|
||||||
try {
|
|
||||||
cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
|
|
||||||
cs.start();
|
|
||||||
JMXServiceURL addr = cs.getAddress();
|
|
||||||
cc = JMXConnectorFactory.connect(addr);
|
|
||||||
MBeanServerConnection mbsc = cc.getMBeanServerConnection();
|
|
||||||
ObjectName name = new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME);
|
|
||||||
System.out.println("DiagnosticCommand MBean: " + name);
|
|
||||||
System.out.println("DcmdMBeanRunner COMPLETE");
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
cc.close();
|
|
||||||
cs.stop();
|
|
||||||
} catch (Exception e) { /* ignored */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue