6436034: Instance filter doesn't filter event if it occurs in native method
Use 'GetLocalInstance' JVMTI extension if it exists Reviewed-by: coleenp, dcubed
This commit is contained in:
parent
677a39996a
commit
8867f6b298
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2010, 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
|
||||
@ -133,27 +133,60 @@ set_event_notification(jvmtiEventMode mode, EventIndex ei)
|
||||
return error;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int major;
|
||||
int minor;
|
||||
} version_type;
|
||||
|
||||
typedef struct {
|
||||
version_type runtime;
|
||||
version_type compiletime;
|
||||
} compatible_versions_type;
|
||||
|
||||
/*
|
||||
* List of explicitly compatible JVMTI versions, specified as
|
||||
* { runtime version, compile-time version } pairs. -1 is a wildcard.
|
||||
*/
|
||||
static int nof_compatible_versions = 3;
|
||||
static compatible_versions_type compatible_versions_list[] = {
|
||||
/*
|
||||
* FIXUP: Allow version 0 to be compatible with anything
|
||||
* Special check for FCS of 1.0.
|
||||
*/
|
||||
{ { 0, -1 }, { -1, -1 } },
|
||||
{ { -1, -1 }, { 0, -1 } },
|
||||
/*
|
||||
* 1.2 is runtime compatible with 1.1 -- just make sure to check the
|
||||
* version before using any new 1.2 features
|
||||
*/
|
||||
{ { 1, 1 }, { 1, 2 } }
|
||||
};
|
||||
|
||||
|
||||
/* Logic to determine JVMTI version compatibility */
|
||||
static jboolean
|
||||
compatible_versions(jint major_runtime, jint minor_runtime,
|
||||
jint major_compiletime, jint minor_compiletime)
|
||||
{
|
||||
#if 1 /* FIXUP: We allow version 0 to be compatible with anything */
|
||||
/* Special check for FCS of 1.0. */
|
||||
if ( major_runtime == 0 || major_compiletime == 0 ) {
|
||||
return JNI_TRUE;
|
||||
/*
|
||||
* First check to see if versions are explicitly compatible via the
|
||||
* list specified above.
|
||||
*/
|
||||
int i;
|
||||
for (i = 0; i < nof_compatible_versions; ++i) {
|
||||
version_type runtime = compatible_versions_list[i].runtime;
|
||||
version_type comptime = compatible_versions_list[i].compiletime;
|
||||
|
||||
if ((major_runtime == runtime.major || runtime.major == -1) &&
|
||||
(minor_runtime == runtime.minor || runtime.minor == -1) &&
|
||||
(major_compiletime == comptime.major || comptime.major == -1) &&
|
||||
(minor_compiletime == comptime.minor || comptime.minor == -1)) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Runtime major version must match. */
|
||||
if ( major_runtime != major_compiletime ) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/* Runtime minor version must be >= the version compiled with. */
|
||||
if ( minor_runtime < minor_compiletime ) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/* Assumed compatible */
|
||||
return JNI_TRUE;
|
||||
|
||||
return major_runtime == major_compiletime &&
|
||||
minor_runtime >= minor_compiletime;
|
||||
}
|
||||
|
||||
/* OnLoad startup:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2010, 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
|
||||
@ -39,6 +39,7 @@
|
||||
#include "stepControl.h"
|
||||
#include "threadControl.h"
|
||||
#include "SDE.h"
|
||||
#include "jvmti.h"
|
||||
|
||||
typedef struct ClassFilter {
|
||||
jclass clazz;
|
||||
@ -275,6 +276,24 @@ patternStringMatch(char *classname, const char *pattern)
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean isVersionGte12x() {
|
||||
jint version;
|
||||
jvmtiError err =
|
||||
JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)(gdata->jvmti, &version);
|
||||
|
||||
if (err == JVMTI_ERROR_NONE) {
|
||||
jint major, minor;
|
||||
|
||||
major = (version & JVMTI_VERSION_MASK_MAJOR)
|
||||
>> JVMTI_VERSION_SHIFT_MAJOR;
|
||||
minor = (version & JVMTI_VERSION_MASK_MINOR)
|
||||
>> JVMTI_VERSION_SHIFT_MINOR;
|
||||
return (major > 1 || major == 1 && minor >= 2);
|
||||
} else {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the object instance in which the event occurred */
|
||||
/* Return NULL if static or if an error occurs */
|
||||
static jobject
|
||||
@ -286,6 +305,14 @@ eventInstance(EventInfo *evinfo)
|
||||
jint modifiers = 0;
|
||||
jvmtiError error;
|
||||
|
||||
static jboolean got_version = JNI_FALSE;
|
||||
static jboolean is_version_gte_12x = JNI_FALSE;
|
||||
|
||||
if (!got_version) {
|
||||
is_version_gte_12x = isVersionGte12x();
|
||||
got_version = JNI_TRUE;
|
||||
}
|
||||
|
||||
switch (evinfo->ei) {
|
||||
case EI_SINGLE_STEP:
|
||||
case EI_BREAKPOINT:
|
||||
@ -314,11 +341,18 @@ eventInstance(EventInfo *evinfo)
|
||||
/* fail if error or static (0x8) */
|
||||
if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) {
|
||||
FrameNumber fnum = 0;
|
||||
/* get slot zero object "this" */
|
||||
error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
|
||||
(gdata->jvmti, thread, fnum, 0, &object);
|
||||
if (error != JVMTI_ERROR_NONE)
|
||||
if (is_version_gte_12x) {
|
||||
/* Use new 1.2.x function, GetLocalInstance */
|
||||
error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance)
|
||||
(gdata->jvmti, thread, fnum, &object);
|
||||
} else {
|
||||
/* get slot zero object "this" */
|
||||
error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
|
||||
(gdata->jvmti, thread, fnum, 0, &object);
|
||||
}
|
||||
if (error != JVMTI_ERROR_NONE) {
|
||||
object = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
|
@ -209,7 +209,7 @@ createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) {
|
||||
*agent_ptr = NULL;
|
||||
jnierror = (*vm)->GetEnv( vm,
|
||||
(void **) &jvmtienv,
|
||||
JVMTI_VERSION);
|
||||
JVMTI_VERSION_1_1);
|
||||
if ( jnierror != JNI_OK ) {
|
||||
initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
|
||||
} else {
|
||||
@ -990,7 +990,7 @@ retransformableEnvironment(JPLISAgent * agent) {
|
||||
}
|
||||
jnierror = (*agent->mJVM)->GetEnv( agent->mJVM,
|
||||
(void **) &retransformerEnv,
|
||||
JVMTI_VERSION);
|
||||
JVMTI_VERSION_1_1);
|
||||
if ( jnierror != JNI_OK ) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, 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
|
||||
@ -41,8 +41,9 @@ enum {
|
||||
JVMTI_VERSION_1 = 0x30010000,
|
||||
JVMTI_VERSION_1_0 = 0x30010000,
|
||||
JVMTI_VERSION_1_1 = 0x30010100,
|
||||
JVMTI_VERSION_1_2 = 0x30010200,
|
||||
|
||||
JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (1 * 0x100) + 102 /* version: 1.1.102 */
|
||||
JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
@ -1774,6 +1775,12 @@ typedef struct jvmtiInterface_1_ {
|
||||
jobject object,
|
||||
jlong* size_ptr);
|
||||
|
||||
/* 155 : Get Local Instance */
|
||||
jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
|
||||
jthread thread,
|
||||
jint depth,
|
||||
jobject* value_ptr);
|
||||
|
||||
} jvmtiInterface_1;
|
||||
|
||||
struct _jvmtiEnv {
|
||||
@ -2031,6 +2038,12 @@ struct _jvmtiEnv {
|
||||
return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
|
||||
}
|
||||
|
||||
jvmtiError GetLocalInstance(jthread thread,
|
||||
jint depth,
|
||||
jobject* value_ptr) {
|
||||
return functions->GetLocalInstance(this, thread, depth, value_ptr);
|
||||
}
|
||||
|
||||
jvmtiError GetLocalInt(jthread thread,
|
||||
jint depth,
|
||||
jint slot,
|
||||
@ -2518,3 +2531,4 @@ struct _jvmtiEnv {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !_JAVA_JVMTI_H_ */
|
||||
|
||||
|
122
jdk/test/com/sun/jdi/NativeInstanceFilter.java
Normal file
122
jdk/test/com/sun/jdi/NativeInstanceFilter.java
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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 6426034
|
||||
* @summary Instance filter doesn't filter event if it occurs in native method
|
||||
*
|
||||
* @author Keith McGuigan
|
||||
*
|
||||
* @library scaffold
|
||||
* @run build JDIScaffold VMConnection
|
||||
* @compile -XDignore.symbol.file NativeInstanceFilterTarg.java
|
||||
* @run main/othervm NativeInstanceFilter
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test tests instance filters for events generated from a native method
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import com.sun.jdi.*;
|
||||
import com.sun.jdi.event.*;
|
||||
import com.sun.jdi.request.*;
|
||||
|
||||
public class NativeInstanceFilter extends JDIScaffold {
|
||||
|
||||
static int unfilteredEvents = 0;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
new NativeInstanceFilter().startTests();
|
||||
}
|
||||
|
||||
public NativeInstanceFilter() {
|
||||
super();
|
||||
}
|
||||
|
||||
static EventRequestManager requestManager = null;
|
||||
static MethodExitRequest request = null;
|
||||
|
||||
private void listen() {
|
||||
TargetAdapter adapter = new TargetAdapter() {
|
||||
EventSet set = null;
|
||||
ObjectReference instance = null;
|
||||
|
||||
public boolean eventSetReceived(EventSet set) {
|
||||
this.set = set;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean methodExited(MethodExitEvent event) {
|
||||
String name = event.method().name();
|
||||
if (instance == null && name.equals("latch")) {
|
||||
// Grab the instance (return value) and set up as filter
|
||||
System.out.println("Setting up instance filter");
|
||||
instance = (ObjectReference)event.returnValue();
|
||||
requestManager.deleteEventRequest(request);
|
||||
request = requestManager.createMethodExitRequest();
|
||||
request.addInstanceFilter(instance);
|
||||
request.enable();
|
||||
} else if (instance != null && name.equals("intern")) {
|
||||
// If not for the filter, this will be called twice
|
||||
System.out.println("method exit event (String.intern())");
|
||||
++unfilteredEvents;
|
||||
}
|
||||
set.resume();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
addListener(adapter);
|
||||
}
|
||||
|
||||
|
||||
protected void runTests() throws Exception {
|
||||
String[] args = new String[2];
|
||||
args[0] = "-connect";
|
||||
args[1] = "com.sun.jdi.CommandLineLaunch:main=NativeInstanceFilterTarg";
|
||||
|
||||
connect(args);
|
||||
waitForVMStart();
|
||||
|
||||
// VM has started, but hasn't started running the test program yet.
|
||||
requestManager = vm().eventRequestManager();
|
||||
ReferenceType referenceType =
|
||||
resumeToPrepareOf("NativeInstanceFilterTarg").referenceType();
|
||||
|
||||
request = requestManager.createMethodExitRequest();
|
||||
request.enable();
|
||||
|
||||
listen();
|
||||
|
||||
vm().resume();
|
||||
|
||||
waitForVMDeath();
|
||||
|
||||
if (unfilteredEvents != 1) {
|
||||
throw new Exception(
|
||||
"Failed: Event from native frame not filtered out.");
|
||||
}
|
||||
System.out.println("Passed: Event filtered out.");
|
||||
}
|
||||
}
|
56
jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java
Normal file
56
jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*/
|
||||
|
||||
import sun.misc.Version;
|
||||
|
||||
public class NativeInstanceFilterTarg {
|
||||
|
||||
public static void main(String args[]) {
|
||||
boolean runTest = jvmSupportsJVMTI_12x();
|
||||
String s1 = "abc";
|
||||
String s2 = "def";
|
||||
latch(s1);
|
||||
s1.intern();
|
||||
if (runTest) {
|
||||
s2.intern(); // this is the call that generates events that ought
|
||||
// to be filtered out.
|
||||
} else {
|
||||
System.out.println("Neutering test since JVMTI 1.2 not supported");
|
||||
}
|
||||
}
|
||||
|
||||
// Used by debugger to get an instance to filter with
|
||||
public static String latch(String s) { return s; }
|
||||
|
||||
public static boolean jvmSupportsJVMTI_12x() {
|
||||
// This fix requires the JVM to support JVMTI 1.2, which doesn't
|
||||
// happen until HSX 20.0, build 05.
|
||||
int major = Version.jvmMajorVersion();
|
||||
int minor = Version.jvmMinorVersion();
|
||||
int micro = Version.jvmMicroVersion();
|
||||
int build = Version.jvmBuildNumber();
|
||||
|
||||
return (major > 20 || major == 20 &&
|
||||
(minor > 0 || micro > 0 || build >= 5));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user