Home » Archived » Test and Performance Tools Platform (TPTP) » jni calls from a c++ tptp agent crashes vm
jni calls from a c++ tptp agent crashes vm [message #105147] |
Mon, 16 July 2007 20:21 |
Eclipse User |
|
|
|
Originally posted by: natashads.gmail.com
Hi All,
This is a bizzare problem I'm encountering. I've written a dual tptp/jvm
agent in the old framework. The JVM_Onload method of the agent waits for
the vm to complete initialization before attempting to register the agent
with the agent controller. After some unspecified amount of time, the
agent receives a command and tries to carry out some jni function calls,
specifically, reading a system property from the vm it is running in.
This seems to be problematic: every vm I've tested on crashes with an
Access violation error at one of the FindClass or GetStaticMethodID
methods, both functions defined by JNI.. I've tested on windows with IBM
1.5 and Sun 1.4 and 1.5. Oddly enough, everything seems to work fine on
an IBM 1.4 JVM, some of the time. I have written a simple agent that has
the same problem, and the full source is below:
To try sending an arbitrary agent a command, you can use the sample
client posted at https://bugs.eclipse.org/bugs/show_bug.cgi?id=187891 and
add the following lines after the attach is complete:
CustomCommand customCommand = new CustomCommand();
customCommand.setData("somecommand");
agent.invokeCustomCommand(customCommand);
Compile flags:
JDK_HOME = D:\ibm_java5_sr5
RAC_LIB_DIR = D:\agnt_ctrl_410\lib
INCLUDES = -I D:\agnt_ctrl_410\include\ -I "C:\Program Files\Microsoft
Visual Studio .NET 2003\Vc7\PlatformSDK\Include" -I .
-I$(JDK_HOME)\include -I$(JDK_HOME)\include\win32
LINKOPTS = kernel32.lib $(RAC_LIB_DIR)\hcbnd.lib
$(RAC_LIB_DIR)\hcclco.lib $(RAC_LIB_DIR)\hccldt.lib
$(RAC_LIB_DIR)\hccls.lib $(RAC_LIB_DIR)\hcclsm.lib
$(RAC_LIB_DIR)\hcjbnd.lib
DEPS = sampleTPTPAgent.cpp
all: sampleTPTPAgent.dll
sampleTPTPAgent.dll: $(DEPS)
cl -LD -MD $(LINKOPTS) -Zi $(INCLUDES) /D"NO_INLINE"
/D"__TOS_WIN__" /Wp64 /EHsc -Tp $(DEPS) -o sampleTPTPAgent.dll
#include "sampleTPTPAgent.h"
static JNIEnv *env = NULL;
static JVMPI_Interface *jvmpi_interface = NULL;
static RA_AGENT_HANDLE handle = NULL;
extern "C" {
JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM *vm, char *options, void
*reserved) {
int result = JNI_OK;
//Setup the JNI env ptr
result = vm->GetEnv((void **)&env, JNI_VERSION_1_2);
if (result != JNI_OK) {
printf("Error occurred getting JNI environment, return code %d\n",
result);
result = JNI_ERR;
} else {
// get jvmpi interface pointer
if ((vm->GetEnv((void **)&jvmpi_interface, JVMPI_VERSION_1_2)) < 0) {
fprintf(stderr, "error initializing jvmpi");
result = JNI_ERR;
} else {
jvmpi_interface->NotifyEvent = notifyEvent;
// register for jvm initialization notification so that we can
// create a thread to register with the AC
jvmpi_interface->EnableEvent(JVMPI_EVENT_JVM_INIT_DONE, NULL);
}
}
return result;
}
}
void notifyEvent(JVMPI_Event *event) {
switch(event->event_type) {
case JVMPI_EVENT_JVM_INIT_DONE:
jvmpi_interface->CreateSystemThread("Register thread",
JVMPI_NORMAL_PRIORITY, registerAgent);
break;
}
}
void getUserDir(void* param){
char *dir = NULL;
jclass cls;
jstring key;
jobject obj;
jstring value;
jmethodID mID;
jsize stringLength;
cls = env->FindClass("java/lang/System");
if (cls != NULL && cls != 0) {
mID = env->GetStaticMethodID(cls, "getProperty",
"(Ljava/lang/String;)Ljava/lang/String;");
if (mID != NULL) {
key = env->NewStringUTF("user.dir";
obj = env->CallStaticObjectMethod(cls, mID, key);
if (obj != NULL) {
value = (jstring) obj;
const char *str = env->GetStringUTFChars(value, 0);
stringLength = env->GetStringUTFLength(value);
dir = (char *) malloc(sizeof(char) * stringLength);
strcpy (dir, str);
env->ReleaseStringUTFChars(value, str);
}
}
}
}
if (dir != NULL) {
fprintf(stderr, "dir: %s\n", dir); //Pring out working direcotry
}
}
void incomingCommand(ra_command_t *command) {
switch (command->tag) {
case RA_CUSTOM_COMMAND:
getUserDir(NULL); //try getting the "user.dir" system property
break;
}
}
/**Registers the agent with the agent controller */
void registerAgent(void *param) {
TID *tid;
//initialize rac libraries
handle = ra_initializeBindings("sample.tptp.agent", "Profiler",
incomingCommand, FALSE);
if (handle == NULL) {
fprintf(stderr, "Could not initialize agent\n");
} else {
fprintf(stderr, "agent intialized\n");
tid = ra_startListener(handle, 0 );
if (tid != NULL) {
fprintf(stderr, "agent ready to receive commands!\n");
}
}
fflush(stderr);
}
void notifyEvent(JVMPI_Event *event) {
switch(event->event_type) {
case JVMPI_EVENT_JVM_INIT_DONE:
jvmpi_interface->CreateSystemThread("Register thread",
JVMPI_NORMAL_PRIORITY, registerAgent);
break;
case JVMPI_EVENT_JVM_SHUT_DOWN:
if (handle != NULL && handle->registered) {
ra_stopListener(handle);
ra_finalizeBindings(handle);
handle = NULL;
}
break;
}
}
|
|
| |
Re: jni calls from a c++ tptp agent crashes vm [message #105349 is a reply to message #105260] |
Tue, 17 July 2007 19:36 |
Natasha D'Silva Messages: 25 Registered: July 2009 |
Junior Member |
|
|
Thank you so much! I knew I was doing something wrong!
It works now on all vms, I store the JavaVM pointer and re-use it to attach
the current thread in the incomingCommand() method. I scoured the doc and
can't find anything to suggest I shouldn't do that.
I really appreciate your help, I was quite stumped!
Thanks again,
Natasha D'Silva
"Asaf Yaffe" <asaf.yaffe@intel.com> wrote in message
news:f7ij0d$th3$1@build.eclipse.org...
> Hi,
>
> I can think of two reasons why the code crashes:
> 1. The thread which processes the custom Agent command is not attached to
> the JVM.
>
> 2. (partly related to the previous problem): an incorrect use of the JNI
> environment pointer. JNIEnv pointers are thread-dependent, and cannot be
> shared between multiple threads (you're storing it in a static variable).
> The "env" variable is initialized to the JNIEnv of the thread which loads
> your agent. Most likely, this is not the thread on which the "custom
> command" handler is called. Hence a crash (I am actually surprised this is
> working on some JVMs).
>
> Your "agent command" handler must test whether the current (calling)
> thread is attached to the JVM (and attach it if it is not), and then
> obtain its correct JNI environment.
>
> HTH,
> Asaf
>
> --
> Asaf Yaffe
> Eclipse TPTP Committer, JVMTI Profiler
|
|
|
Goto Forum:
Current Time: Sat Apr 27 01:03:45 GMT 2024
Powered by FUDForum. Page generated in 0.03933 seconds
|