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
jdk
src/share
test/com/sun/jdi
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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;
|
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 */
|
/* Logic to determine JVMTI version compatibility */
|
||||||
static jboolean
|
static jboolean
|
||||||
compatible_versions(jint major_runtime, jint minor_runtime,
|
compatible_versions(jint major_runtime, jint minor_runtime,
|
||||||
jint major_compiletime, jint minor_compiletime)
|
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. */
|
* First check to see if versions are explicitly compatible via the
|
||||||
if ( major_runtime == 0 || major_compiletime == 0 ) {
|
* list specified above.
|
||||||
return JNI_TRUE;
|
*/
|
||||||
|
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. */
|
return major_runtime == major_compiletime &&
|
||||||
if ( major_runtime != major_compiletime ) {
|
minor_runtime >= minor_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OnLoad startup:
|
/* 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -39,6 +39,7 @@
|
|||||||
#include "stepControl.h"
|
#include "stepControl.h"
|
||||||
#include "threadControl.h"
|
#include "threadControl.h"
|
||||||
#include "SDE.h"
|
#include "SDE.h"
|
||||||
|
#include "jvmti.h"
|
||||||
|
|
||||||
typedef struct ClassFilter {
|
typedef struct ClassFilter {
|
||||||
jclass clazz;
|
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 the object instance in which the event occurred */
|
||||||
/* Return NULL if static or if an error occurs */
|
/* Return NULL if static or if an error occurs */
|
||||||
static jobject
|
static jobject
|
||||||
@ -286,6 +305,14 @@ eventInstance(EventInfo *evinfo)
|
|||||||
jint modifiers = 0;
|
jint modifiers = 0;
|
||||||
jvmtiError error;
|
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) {
|
switch (evinfo->ei) {
|
||||||
case EI_SINGLE_STEP:
|
case EI_SINGLE_STEP:
|
||||||
case EI_BREAKPOINT:
|
case EI_BREAKPOINT:
|
||||||
@ -314,11 +341,18 @@ eventInstance(EventInfo *evinfo)
|
|||||||
/* fail if error or static (0x8) */
|
/* fail if error or static (0x8) */
|
||||||
if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) {
|
if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) {
|
||||||
FrameNumber fnum = 0;
|
FrameNumber fnum = 0;
|
||||||
/* get slot zero object "this" */
|
if (is_version_gte_12x) {
|
||||||
error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
|
/* Use new 1.2.x function, GetLocalInstance */
|
||||||
(gdata->jvmti, thread, fnum, 0, &object);
|
error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance)
|
||||||
if (error != JVMTI_ERROR_NONE)
|
(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;
|
object = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
|
@ -209,7 +209,7 @@ createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) {
|
|||||||
*agent_ptr = NULL;
|
*agent_ptr = NULL;
|
||||||
jnierror = (*vm)->GetEnv( vm,
|
jnierror = (*vm)->GetEnv( vm,
|
||||||
(void **) &jvmtienv,
|
(void **) &jvmtienv,
|
||||||
JVMTI_VERSION);
|
JVMTI_VERSION_1_1);
|
||||||
if ( jnierror != JNI_OK ) {
|
if ( jnierror != JNI_OK ) {
|
||||||
initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
|
initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
|
||||||
} else {
|
} else {
|
||||||
@ -990,7 +990,7 @@ retransformableEnvironment(JPLISAgent * agent) {
|
|||||||
}
|
}
|
||||||
jnierror = (*agent->mJVM)->GetEnv( agent->mJVM,
|
jnierror = (*agent->mJVM)->GetEnv( agent->mJVM,
|
||||||
(void **) &retransformerEnv,
|
(void **) &retransformerEnv,
|
||||||
JVMTI_VERSION);
|
JVMTI_VERSION_1_1);
|
||||||
if ( jnierror != JNI_OK ) {
|
if ( jnierror != JNI_OK ) {
|
||||||
return NULL;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 = 0x30010000,
|
||||||
JVMTI_VERSION_1_0 = 0x30010000,
|
JVMTI_VERSION_1_0 = 0x30010000,
|
||||||
JVMTI_VERSION_1_1 = 0x30010100,
|
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
|
JNIEXPORT jint JNICALL
|
||||||
@ -1774,6 +1775,12 @@ typedef struct jvmtiInterface_1_ {
|
|||||||
jobject object,
|
jobject object,
|
||||||
jlong* size_ptr);
|
jlong* size_ptr);
|
||||||
|
|
||||||
|
/* 155 : Get Local Instance */
|
||||||
|
jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
|
||||||
|
jthread thread,
|
||||||
|
jint depth,
|
||||||
|
jobject* value_ptr);
|
||||||
|
|
||||||
} jvmtiInterface_1;
|
} jvmtiInterface_1;
|
||||||
|
|
||||||
struct _jvmtiEnv {
|
struct _jvmtiEnv {
|
||||||
@ -2031,6 +2038,12 @@ struct _jvmtiEnv {
|
|||||||
return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
|
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,
|
jvmtiError GetLocalInt(jthread thread,
|
||||||
jint depth,
|
jint depth,
|
||||||
jint slot,
|
jint slot,
|
||||||
@ -2518,3 +2531,4 @@ struct _jvmtiEnv {
|
|||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif /* !_JAVA_JVMTI_H_ */
|
#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