call java from c++: where to put class

T

tony_lincoln

Dear friends,

I am using JNI to call java from C++. I use j2sdk1.4.1 and Visual C++
6.
Parameter setting in Visual C++ 6:

In Tools¡úOptions->Include Files:
1. C:\j2sdk1.4.1_02\include
2. C:\j2sdk1.4.1_02\include\win32

In Tools->Options->Library Files:
C:\j2sdk1.4.1_02\lib

set Path = C:\j2sdk1.4.1_02\jre\bin\client

All of these settings are correct. When I compiled the invoke.cpp, no
errors. But when I execute it, DOS concole window popped up and one
sentence appeared:
"Sorry, I can't find the class. Press any key to continue"

The "Sorry, I can't find the class" came from my invoke.cpp. This
means, this cpp can not find my java class, even when I put the java
class "Demo" into the same subdir as invoke.cpp. Where should I put the
Demo class?

Any hints? Thanks a lot!

The related codes(Demo.java, invoke.cpp) are enclosed here:

//Demo.java
************************************************
package jni.test;

public class Demo {

public static int COUNT = 8;
public String msg;
private int[] counts;
public Demo() {
this("ȱʡ¹¹Ô캯Êý");
}

public Demo(String msg) {
System.out.println("<init>:" + msg);
this.msg = msg;
this.counts = null;
}

public String getMessage() {
return msg;
}

public int[] getCounts(){
return counts;
}

public void setCounts(int[] counts){
this.counts = counts;
}

public void throwExcp()
throws IllegalAccessException{
throw new IllegalAccessException
("exception occur.");
}

}// end class Demo.

*****************************************************************+




The c++ code is the following:
// invoke.cpp
********************************************************************
/*for C++,debugged with Visual C++ 6.0*/

#ifndef __cplusplus
#define __cplusplus
#endif

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#pragma comment (lib,"C:\\j2sdk1.4.1_02\\lib\\jvm.lib")

int JStringToChar(JNIEnv *env, jstring str, LPTSTR desc, int desc_len)
{
int len = 0;
if(desc==NULL||str==NULL)
return -1;

wchar_t *w_buffer = new wchar_t[1024];
ZeroMemory(w_buffer,1024*sizeof(wchar_t));

wcscpy(w_buffer,env->GetStringChars(str,0));

env->ReleaseStringChars(str,w_buffer);
ZeroMemory(desc,desc_len);

len =
WideCharToMultiByte(CP_ACP,0,w_buffer,1024,desc,desc_len,NULL,NULL);

if(len>0 && len<desc_len) desc[len]=0;
delete[] w_buffer;
return strlen(desc);
}

jstring NewJString(JNIEnv* env,LPTSTR str)
{
if(!env || !str) return 0;
int slen = strlen(str);
jchar* buffer = new jchar[slen];
int len = MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,slen);
if(len>0 && len < slen) buffer[len]=0;
jstring js = env->NewString(buffer,len);
delete [] buffer;
return js;
}


void main() {

JavaVM *jvm;
JNIEnv *env;

JavaVMInitArgs vm_args;
JavaVMOption options[3];

options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "";

vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;

jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
};
jclass cls = env->FindClass("Demo");

if (cls == 0) printf("Sorry, I can't find the class");

jmethodID get_main_id =
env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
jclass string = env->FindClass("java/lang/String");
jobjectArray args = env->NewObjectArray(0,string, NULL);
env->CallStaticVoidMethod(cls,get_main_id,args);

jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}//end main.

***********************************************************************
//end of invoke.cpp
 
G

Gordon Beaton

package jni.test;
public class Demo {
[...]

jclass cls = env->FindClass("Demo");
if (cls == 0) printf("Sorry, I can't find the class");

You spelled the name of the class wrong. Try "jni.test.Demo" or remove
the package declaration. Note too that the class should be in
../jni/test/Demo.class if your classpath points to "." as it does in
the code you've posted.
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "";
vm_args.nOptions = 3;

I see only two meaningful arguments here. Why the empty string?

/gordon
 
T

tony_lincoln

Thanks a lot. I removed "package Jni.test;" in the Demo.java and
compile it again, and it works.
( options[2].optionString = "-verbose: jni" )
But new question comes:
When the c++ codes run, a DOS console poped up, and the words like this
appears:

___________________________________________________________________________________
....
[Dynamic-linking native method java.lang.Thread start0 ... JNI]
....
[Dynamic-linking native method java.lang.classLoader defineClass1 ...
JNI]
---------------------------------------------------------------------------------------------------------------------

Then a new Windows from Win2000 popped up and showed:
"Test3_14Aug.exe has encountered a problem and needs to close.We are
sorry from the inconvenience.
Please tell Microsoft about this problem.
We have created an error report that you can send to us...."

Then the program was forced to stop.
Is this the problem of win2000, or the bug in invoke.cpp/Demo.java?
Thanks in advance.
tony
 
G

Gordon Beaton

"Test3_14Aug.exe has encountered a problem and needs to close.We are
sorry from the inconvenience.
Please tell Microsoft about this problem.
We have created an error report that you can send to us...."

Then the program was forced to stop.

In the code you've posted, Demo doesn't have a main() method and you
don't check the return value from GetStaticMethodID() before
attempting to invoke it.

/gordon
 
T

tony_lincoln

Thank you very much. You are right. Once I put main() method in it, it
works. Thanks.
Tony
 
T

tony_lincoln

But the new problem about package comes:

In my Java source code:
********************************************************
import com.tony.package1.classA;
....
public static void main(String[] args) {
System.out.println("This is a test");
String [] str = new classA.method1();
}
....
*********************************************************

When I invoke this java class from C++ codes in Visual C++, the "This
is a test" can be shown in DOS shell, then it shows:
" An unexpected error has been detected by HotSpot Virtual Machine:
Internal Error (57437914380392184392743120947000FF),
pid = 3288, tid = 3292.
...."

So I thought this is the problem of path setting. I set the path as
E:\codes_Tony. This dir is where I put my package com.tony.package1.*.
But the same error apprears.
I still guess that this is the problem of path setting. But how?
Thanks a lot.
Tony
 
T

tony_lincoln

Exactly. E:\codes_Tony is in my classpath, and com.tony.package1.ClassA
is in E:\codes_Tony\com\tony\package 1\ClassA.class.
But why the error appears:
" An unexpected error has been detected by HotSpot Virtual Machine:
Internal Error (57437914380392184392743120947 000FF),
pid = 3288, tid = 3292.
..."
To do with this error, any hints?
Thanks in advance.
Tony
 
A

Andrew Thompson

Exactly. E:\codes_Tony is in my classpath, and com.tony.package1.ClassA
is in E:\codes_Tony\com\tony\package 1\ClassA.class.

Compare ..
E:\codes_Tony\com\tony\package 1\ClassA.class
...to..
E:\codes_Tony\com\tony\package1\ClassA.class
 
T

tony_lincoln

You are right. But what I want to say is,

E:\codes_Tony is in my classpath, and com.tony.package1.ClassA
is in E:\codes_Tony\com\tony\package1\ClassA.class.
But why the error appears:
" An unexpected error has been detected by HotSpot Virtual Machine:
Internal Error (57437914380392184392743120947 000FF),
pid = 3288, tid = 3292.
..."
To do with this error, any hints?
Thanks in advance.
Tony
 
A

Andrew Thompson

You are right. But what I want to say is, ..

Hold it!

In that case, some advice.

Stop 'typing' the paths and package names.
Copy/paste the information instead. You are
simply wasting time otherwise.
 
T

tony_lincoln

So you mean that I should change the original source code
******************************­**************************
import com.tony.package1.classA;
....
public static void main(String[] args) {
System.out.println("This is a test");
String [] str = new classA.method1();
}
....
******************************­***************************

into
******************************­**************************
// here without writting "import ..."
....
public static void main(String[] args) {
System.out.println("This is a test");
String [] str = new classA.method1();
}
....
******************************­***************************
and put classA into the dir which is same as my source code?
But this won't work...as classA was produced as a form of package...
 
A

Andrew Thompson

On 16 Aug 2005 09:46:11 -0700, (e-mail address removed) wrote:

(A.T. earlier)
...
So you mean that I should change the original source code

No...

My point was - Be precise, rather than approximate.

When you type a path or classname, or some error output,
there is room for 'typos'. So - *don't* type it.

Allways *copy* the output from the command line,
or error log, the address bar of the directory,
or batch file.. wherever it actually occurs.
 
G

Gordon Beaton

E:\codes_Tony is in my classpath, and com.tony.package1.ClassA
is in E:\codes_Tony\com\tony\package1\ClassA.class.
But why the error appears:
" An unexpected error has been detected by HotSpot Virtual Machine:
Internal Error (57437914380392184392743120947 000FF),
pid = 3288, tid = 3292.
..."
To do with this error, any hints?

This can be caused by many things, and all of them are errors in your
code.

In the code you posted earlier you had neglected to check return
values from the various JNI functions you are calling. Before we
continue to try to guess why your code is crashing, you need to add
code to check the return values you were previously ignoring.

If FindClass() fails and you continue to look up a method using the
NULL value, your code will crash. If GetMethodID() fails and you
continue to invoke the NULL method, your code will crash. And so on.

Check the return values, and when one of them fails to return what you
expect, use something like this to see why:

cls = env->FindClass("com/tony/package1/ClassA");

if (cls != NULL) {
mid = env->GetStaticMethodID(...);

if (mid != NULL) {
env->CallStaticVoidMethod(...);
}
}

if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
}

If your code continues to crash after that, you need to post more
information, e.g. the real code you are using, and the exact point of
the crash (which you can determine quickly using a debugger or simple
print statements).

/gordon
 
T

tony_lincoln

I do not think that there is errors in my source code. I made a test
and the source code is following:
DemoMain.java is the java code invoked by C++ code. IOTest.class is the
java class used by DemoMain.

DemoMain.java
******************************************************************************************************
import com.tony.jniClasses.IOTest;
import java.io.*;

public class DemoMain {
public static void main(String[] args)
throws java.io.IOException, java.lang.NullPointerException
{
System.out.println("This is a test.");
IOTest.printLines();
}// end main().
}// end class DemoMain.
**************************************************************************************************************************


IOTest.java
**************************************************************************************************************************
package com.tony.jniClasses;
import java.io.*;

public class IOTest
{
public static void printLines()
{
System.out.println("Line 1: no input, no output");
System.out.println("Line 2: no input, no output");
}// end printLines()
}// end class IOTest.
*****************************************************************************************************************

When I run the c++ code under Visual C++ studio 6.0,
the "This is a test" can be shown in DOS shell, then it shows:
" An unexpected error has been detected by HotSpot Virtual Machine:
Internal Error (57437914380392184392743120947­000FF),
pid = 3288, tid = 3292.
...."

What is error ????? Any hints?
TOny
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top