Access violation Exception in JNI VC++ code.
I have a main method in a VC++ class, in which i am creating\instantiating JVM.
In main method i am calling a method of my own utility class to create JVM.
I am cacheing JVM pointer in a private member variable.
I am using following code to create an object of class -
com/spss/java_client/core/script/COM/SpssCSApp
// getJvm function returns JavaVM interface pointer that was used while creating jvm
JavaVM*curr_jvm = getJvm();
JNIEnv* t_env;
curr_jvm->AttachCurrentThread((void **)&t_env, NULL);
if (t_env->ExceptionOccurred()){
t_env->ExceptionDescribe();
}
// Create an instance of ISpssApp
csAppClazz = t_env->FindClass("com/spss/java_client/core/script/COM/SpssCSApp");
if (t_env->ExceptionOccurred()){
t_env->ExceptionDescribe();
}
jmethodID mid = t_env->GetMethodID(csAppClazz,"<init>","()V");
if (t_env->ExceptionOccurred()){
t_env->ExceptionDescribe();
}
csApp = t_env->NewObject(csAppClazz, mid);
if (t_env->ExceptionOccurred()){
t_env->ExceptionDescribe();
}
After the call to t_env->FindClass my VC++ debug output shows following error -
First-chance exception at 0x00cb74bf in JNIEXE.exe: 0xC0000005: Access violation reading location 0x00000000
But the subsequent call to t_env->ExceptionOccurred returns false.
Also rest of the program runs fine.
I mean even if this exception is shown in debug output window, the creation of new objects in JVM doesn't fail.
So i am not able to detect what is the cause of this exception.
Can anybody help me out with this problem.
[2243 byte] By [
atul_pa] at [2007-10-3 3:26:12]

Hi jschell , below you can find source code of my applicatrion.
1. Class JNIEXE.cpp defines main method.
2. Class SpssCsApp creates JVM and starts my java application by invoking main method of java class Driver.
3. Class JvmAppArgs and SpssLauncher are used to create JVM and start application.
4. I have written comments in startApplication method of SpssLauncher class that shows exactly where access violation occurs.
// JNIEXE.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "SpssCSApp.h"
int main(int argc, char* argv[])
{
SpssCSApp objSPSS;
Sleep(5000);
SpssLauncher::getLauncher()->getJvm()->DetachCurrentThread();
SpssLauncher::getLauncher()->getJvm()->DestroyJavaVM();
}
// SpssCSApp.h : Declaration of the SpssCSApp.
#ifndef __SPSSCSAPP_H_
#define __SPSSCSAPP_H_
#include "SpssServers.h"
#include "SpssDocuments.h"
#include "SpssLauncher.h"
#include <jni.h>
class SpssCSApp
{
private:
SpssLauncher* launcher;
jobject csApp;
jclass csAppClazz;
public:
SpssCSApp();
};
#endif //__SPSSCSAPP_H_
// SpssCSApp.cpp : Implementation of SpssCSApp.
#include "stdafx.h"
#include "SpssCSApp.h"
#include "SpssLauncher.h"
#include <jni.h>
#define CLASSNAME "com/spss/java_client/ui/Driver"
SpssCSApp::SpssCSApp()
{
JvmAppArgs*svc_args;
SpssLauncher* jvmProvider;
jvmProvider = SpssLauncher::getLauncher();
jvmProvider->startJvm();
svc_args = new JvmAppArgs();
svc_args->setClass(CLASSNAME);
svc_args->setJvmService(jvmProvider);
jvmProvider->startApplication(svc_args);
JavaVM*curr_jvm = SpssLauncher::getLauncher()->getJvm();
JNIEnv* t_env;
curr_jvm->AttachCurrentThread((void **)&t_env, NULL);
if (t_env->ExceptionOccurred()) {
t_env->ExceptionDescribe();
}
// Create an instance of ISpssApp
csAppClazz = t_env->FindClass("com/spss/java_client/core/script/COM/SpssCSApp");
if (t_env->ExceptionOccurred()) {
t_env->ExceptionDescribe();
}
jmethodID mid = t_env->GetMethodID(csAppClazz, "<init>", "()V");
if (t_env->ExceptionOccurred()) {
t_env->ExceptionDescribe();
}
csApp = t_env->NewObject(csAppClazz, mid);
if (t_env->ExceptionOccurred()) {
t_env->ExceptionDescribe();
}
delete svc_args;
}
// JvmAppArgs.h : Declaration of the JvmAppArgs.
#include "stdafx.h"
#include <jni.h>
class SpssLauncher;
class JvmAppArgs
{
private:
int_argc;// # of args. to 'main' of server
char** _argv;// args to 'main' of server
char* _className;// class from which to invoke 'main'
int_cnt;// How many ptrs alloc'd for arglist
SpssLauncher* _jvmServices;
jobject csApp;
jclass csAppClazz;
void _freeArgList();
public:
JvmAppArgs();
// Getters and setters
char** getArgList();
char* getArg(int);
intgetArgListSize();
char* getClass();
SpssLauncher* getJvmService();
void setArg(char*);
void setArgList(char**);
void setClass(char*);
void setJvmService(SpssLauncher*);
void setCsApp(jobject cs){ csApp=cs;}
void setCsAppClazz(jclass cl){csAppClazz=cl;}
jobject getCsApp(){return csApp;}
jclass getCsAppClazz(){return csAppClazz;}
};
// JvmAppArgs.cpp : Class used to store arguments used for Jvm and Application startup.
#include "stdafx.h"
#include "JvmAppArgs.h"
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
class SpssLauncher;
JvmAppArgs::JvmAppArgs()
{
_argc = 0;
_argv = NULL;
_cnt = 0;
}
char** JvmAppArgs::getArgList()
{
return _argv;
}
int JvmAppArgs::getArgListSize()
{
return _argc;
}
char* JvmAppArgs::getClass()
{
return _className;
}
void JvmAppArgs::setArgList(char** args)
{
if (_argv != NULL)
_freeArgList();
while (*args != NULL)
setArg(*args++);
}
void JvmAppArgs::setArg(char* arg)
{
#define ARGLIST_PGSZ10
if (_argc == _cnt) {
_argv = (char**) realloc(_argv, (ARGLIST_PGSZ + _argc) * sizeof(char*));
_cnt += ARGLIST_PGSZ;
}
_argv[_argc++] = arg;
}
void JvmAppArgs::setClass(char* name)
{
_className = name;
}
void JvmAppArgs::setJvmService(SpssLauncher* svc)
{
_jvmServices = svc;
}
SpssLauncher* JvmAppArgs::getJvmService()
{
return _jvmServices;
}
void JvmAppArgs::_freeArgList()
{
char** p = _argv;
while (*p) {
free(*p);
p++;
}
free(_argv);
_argc = 0;
_argv = NULL;
}
// SpssLauncher.h : Defines a Utility class SpssLauncher
#pragma once
#include "JvmAppArgs.h"
#include <jni.h>
#include <windows.h>
#include <process.h>
class SpssLauncher
{
private:
/* The virtual machine instance */
JavaVM*_jvm;
/*
* List of VM options to be specified when the VM is created.
*/
JavaVMOption *options;
int numOptions, maxOptions;
static SpssLauncher* launcherInstance;
void invokeMain(JNIEnv*, char*, jobjectArray);
jobjectArray makeArgsArray(JNIEnv*, int, char**);
public:
SpssLauncher() { numOptions = maxOptions = 0; options = NULL; }
~SpssLauncher();
int startJvm();
JavaVM*getJvm();
void startApplication(JvmAppArgs*);
void * MemAlloc(size_t size);
void AddOption(char *str, void *info);
void SetClassPath(char *s);
static SpssLauncher* getLauncher(void);
};
// SpssLauncher.cpp : Acts as a Utility class, Primarily used for initialization of Jvm and Application.
#if !defined(_MT)
#error _beginthreadex requires a multithreaded C run-time library.
#endif
#include "stdafx.h"
#include "SpssLauncher.h"
#include <windows.h>
#include <process.h>
#include <assert.h>
#include <jni.h>
#define PATH_SEPARATOR ';'
#define USER_CLASSPATH "E:\\java_client_main_branch\\java_client\\java_client\\bin;E:\\java_client_main_branch\\java_client\\java_client\\ui\\lib\\looks-1.3.2.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\xml-apis.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\xercesImpl.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\commons-codec-1.3.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\xmlrpc-2.0.1.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\Editor.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\viseditor\\visualization.jar;E:\\java_client_main_branch\\java_client\\java_client\\core\\lib\\viseditor\\jai_codec.jar"
#define JAVA_LIB_PATH_OPTION "-Djava.library.path=E:\\java_client_main_branch\\java_client"
#define APPLICATION_HOME_OPTION "-Dapplication.home=E:\\java_client_main_branch\\java_client"
/*
* Returns a pointer to a block of at least 'size' bytes of memory.
* Prints error message and exits if the memory could not be allocated.
*/
void *SpssLauncher::MemAlloc(size_t size)
{
void *p = malloc(size);
if (p == 0) {
perror("malloc");
exit(1);
}
return p;
}
/*
* Adds a new VM option with the given given name and value.
*/
void SpssLauncher::AddOption(char *str, void *info)
{
/*
* Expand options array if needed to accommodate at least one more
* VM option.
*/
if (numOptions >= maxOptions) {
if (options == 0) {
maxOptions = 4;
options = (JavaVMOption *)MemAlloc(maxOptions * sizeof(JavaVMOption));
} else {
JavaVMOption *tmp;
maxOptions *= 2;
tmp = (JavaVMOption *)MemAlloc(maxOptions * sizeof(JavaVMOption));
memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
free(options);
options = tmp;
}
}
options[numOptions].optionString = str;
options[numOptions++].extraInfo = info;
}
void SpssLauncher::SetClassPath(char *s)
{
char *def = (char *)MemAlloc(strlen(s) + 40);
sprintf_s(def, (strlen(s) + 40), "-Djava.class.path=%s", s);
AddOption(def, NULL);
}
JavaVM* SpssLauncher::getJvm()
{
return _jvm;
}
int SpssLauncher::startJvm()
{
JavaVMInitArgs vm_args;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
SetClassPath(USER_CLASSPATH);
AddOption(JAVA_LIB_PATH_OPTION, NULL);
AddOption(APPLICATION_HOME_OPTION, NULL);
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = numOptions;
vm_args.ignoreUnrecognized = JNI_TRUE;
JNIEnv* env;
/* Create the Java VM */
if (JNI_CreateJavaVM(&_jvm, (void**)&env, &vm_args) < 0) {
fprintf(stderr, "could not create JVM\n");
free(options);
return 0;
}
free(options);
return 1;
}
SpssLauncher::~SpssLauncher()
{
//assert(_jvm != NULL);
//if(_jvm!=NULL)
_jvm->DestroyJavaVM();
}
/*
* Call the Java method 'public static void main'
*/
void SpssLauncher::invokeMain(JNIEnv* env, char* className, jobjectArray args)
{
jclass clazz = env->FindClass(className);
jmethodID mid = env->GetStaticMethodID(clazz,
"main","([Ljava/lang/String;)V");
env->CallStaticVoidMethod(clazz,mid,args);
}
jobjectArray SpssLauncher::makeArgsArray(JNIEnv* env, int argc, char** argv)
{
int i;
jstring jstr;
jclass clazz = env->FindClass("java/lang/String");
jobjectArray ja = env->NewObjectArray(argc,clazz,NULL);
for(i=0; i < argc; i++) {
jstr = env->NewStringUTF(argv[i]);
env->SetObjectArrayElement(ja,i,jstr);
}
return ja;
}
void SpssLauncher::startApplication(JvmAppArgs* args)
{
JvmAppArgs* appArgs = (JvmAppArgs*) args;
jobjectArrayja;
JNIEnv*t_env;
JavaVM*curr_jvm = SpssLauncher::getLauncher()->getJvm();
curr_jvm->GetEnv((void **)&t_env, JNI_VERSION_1_2);
Sleep(1000);
// UPTILL THIS ACCESS VOILATION HAS NOT BEEN OCCURED
ja = this->makeArgsArray(t_env,
appArgs->getArgListSize(),
appArgs->getArgList());
Sleep(1000);
this->invokeMain(t_env, appArgs->getClass(), ja);
Sleep(1000);
// AFTER THE ABOVE SLEEP CALL VC++ DEBUG OUTPUT WINDOW SHOWS ACCESS VIOLATION EXCEPTION
// BUT STILL THINGS WORK PROPERLY AFTER THIS
if ((*t_env).ExceptionOccurred()) {
(*t_env).ExceptionDescribe();
}
}
SpssLauncher * SpssLauncher::launcherInstance = NULL;
SpssLauncher* SpssLauncher::getLauncher(void)
{
if(launcherInstance == NULL)
{
launcherInstance = new SpssLauncher();
}
return launcherInstance;
}