Discussion:
call java from c++: where to put class
(too old to reply)
t***@yahoo.com
2005-08-14 20:36:57 UTC
Permalink
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
Gordon Beaton
2005-08-15 07:00:30 UTC
Permalink
Post by t***@yahoo.com
package jni.test;
public class Demo {
[...]
Post by t***@yahoo.com
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.
Post by t***@yahoo.com
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
--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
Gordon Beaton
2005-08-15 07:05:37 UTC
Permalink
Post by Gordon Beaton
You spelled the name of the class wrong. Try "jni.test.Demo"
Sorry, that should have been: "jni/test/Demo" instead.

/gordon
--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
Chris Uppal
2005-08-15 07:13:01 UTC
Permalink
Post by Gordon Beaton
Post by t***@yahoo.com
jclass cls = env->FindClass("Demo");
[...]
You spelled the name of the class wrong. Try "jni.test.Demo"
Should be:

"jni/test/Demo"

JNI names....

--- chris
t***@yahoo.com
2005-08-15 13:39:55 UTC
Permalink
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
Gordon Beaton
2005-08-15 13:47:18 UTC
Permalink
Post by t***@yahoo.com
"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
--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
t***@yahoo.com
2005-08-16 13:22:14 UTC
Permalink
Thank you very much. You are right. Once I put main() method in it, it
works. Thanks.
Tony
t***@yahoo.com
2005-08-16 14:36:40 UTC
Permalink
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
Gordon Beaton
2005-08-16 15:39:58 UTC
Permalink
Post by t***@yahoo.com
I set the path as
E:\codes_Tony. This dir is where I put my package com.tony.package1.*.
But the same error apprears.
If E:\codes_Tony is in your classpath, then com.tony.package1.ClassA
should be in E:\codes_Tony\com\tony\package1\ClassA.class.

See also:
http://www.yoda.arachsys.com/java/packages.html

/gordon
--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
t***@yahoo.com
2005-08-16 15:52:53 UTC
Permalink
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
Andrew Thompson
2005-08-16 16:08:00 UTC
Permalink
Post by t***@yahoo.com
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
--
Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
"I'll sing and I'll be merry when occasion I do see,." Steeleye Span 'All
Around My Hat'
t***@yahoo.com
2005-08-16 16:15:44 UTC
Permalink
What do you mean "compare..."? They are the same... aren't they?
tony
Andrew Thompson
2005-08-16 16:20:25 UTC
Permalink
Post by t***@yahoo.com
What do you mean "compare..."? They are the same... aren't they?
No.
--
Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
"You make connections, you win elections, but that ain't gonna be enough.."
The Angels 'City out of Control'
t***@yahoo.com
2005-08-16 16:29:46 UTC
Permalink
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
Andrew Thompson
2005-08-16 16:36:03 UTC
Permalink
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.
--
Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
"What was it you wanted? Tell me again, I forgot." Bob Dylan 'What Was It
You Wanted'
t***@yahoo.com
2005-08-16 16:46:11 UTC
Permalink
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...
Andrew Thompson
2005-08-16 17:16:47 UTC
Permalink
On 16 Aug 2005 09:46:11 -0700, ***@yahoo.com wrote:

(A.T. earlier)
Post by t***@yahoo.com
Post by Andrew Thompson
Stop 'typing' the paths and package names.
Copy/paste the information instead.
..
Post by t***@yahoo.com
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.
--
Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
"I got a raw deal, so I'm lookin' for a steel.." Tricky 'Black Steel'
Gordon Beaton
2005-08-16 17:21:29 UTC
Permalink
Post by t***@yahoo.com
E:\codes_Tony is in my classpath, and com.tony.package1.ClassA
is in E:\codes_Tony\com\tony\package1\ClassA.class.
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
--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
t***@yahoo.com
2005-08-16 17:30:47 UTC
Permalink
Thanks. I will try this...
Tony
t***@yahoo.com
2005-08-17 08:56:50 UTC
Permalink
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
Gordon Beaton
2005-08-17 09:46:27 UTC
Permalink
Post by t***@yahoo.com
I do not think that there is errors in my source code.
I don't agree.
I was referring to your C++ code, not the Java code. I thought that
was clear from the example in my earlier reply.

/gordon
--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
t***@yahoo.com
2005-08-17 12:39:23 UTC
Permalink
I think that you are correct, now I guess #that this error is caused by
CallStaticVoidMethod() in C++ codes. What I have done to prove this is:
I simplied the C++ codes and Java codes, as following:

/*for C++,debugged with Visual C++ 6.0*/
// invoke.cpp

#ifndef __cplusplus
#define __cplusplus
#endif

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

#pragma comment (lib,"E:\\Programme\\Java\\jdk1.5.0_02\\lib\\jvm.lib")

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 = "-verbose:jni";

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("DemoMain");
if (cls == 0) printf("Sorry, I can't find the class");

jmethodID get_main_id;

if(cls != NULL)
{
get_main_id =
env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");

if(get_main_id != NULL )
{
jclass string = env->FindClass("java/lang/String");
jobjectArray args = env->NewObjectArray(0,string, NULL);

fprintf(stdout, "This is invokeSimplified6.\n");
env->CallStaticVoidMethod(cls, get_main_id, args);
fprintf(stdout, "This is invokeSimplified7.\n");

}// end IF.

}// end IF.


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

**************************************************************************************************************

In the main() of Java codes DemoMain.java, there are only 2 sentences:
System.out.println ("This is a test");
IOTest.print2Lines();

IOTest is another java class located in a different directory. There
are only 2 sentences in print2Lines():
System.out.println ("Line1");
System.out.println ("Line2");

I simply these classes, so no parameter was transmitted in different
methods or classes.
I run the c++ codes, the output is like this:
________________________________________________________________________________
...
This is invokeSimplified6.
[Dynamic-linking native method java.io.FileOutputStream.writeBytes ...
JNI]
This is a test.
This is invokeSimplified7.
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# Internal Error (455843455054494F4E530E43505000FF), pid=3704,
tid=4064
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_02-b09 interpreted mode,
sharing)
# An error report file with more information is saved as
hs_err_pid3704.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
---------------------------------------------------------------------------------------------------------------------------------

So I know that this error is caused by CallStaticVoidMethod(). But how
to change it so the output is correct?
Thanks a lot.
tony

Continue reading on narkive:
Loading...