Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / October 2005

Tip: Looking for answers? Try searching our database.

Under Linux, Call java from C++

Thread view: 
tony_lincoln@yahoo.com - 29 Sep 2005 23:19 GMT
Dear Friends,

Under Linux, I tried to call java from C++ using JNI. The following is
the C++ code which calls one java class named Menu_3D.
When I compiled it using g++, there were many mistakes like:

.......
invoke.cpp:26: error: 'struct JavaVMInitArgs' has no member named
'version'
invoke.cpp:26: error: `JNI_VERSION_1_4' undeclared (first use this
function)
invoke.cpp:27: error: 'struct JavaVMInitArgs' has no member named
'nOptions'
invoke.cpp:31: error: `jint' undeclared (first use this function)
invoke.cpp:31: error: syntax error before `=' token
invoke.cpp:32: error: `res' undeclared (first use this function)
invoke.cpp:41: error: `FindClass' undeclared (first use this function)
invoke.cpp:50: error: `GetStaticMethodID' undeclared (first use this
function)
invoke.cpp:56: error: `NewObjectArray' undeclared (first use this
function)
invoke.cpp:60: error: `CallStaticVoidMethod' undeclared (first use this
  function)
invoke.cpp:73: error: `DestroyJavaVM' undeclared (first use this
function)
.......

The above errors are only one part of the whole errors. I know that I
am wrong in this line:
"#pragma comment
(lib,"E:\\Programme\\Java\\jdk1.5.0_02\\lib\\jvm.lib")"

But how can I find the jvm.lib? I tried and I can not. Does invoke.cpp
need jvm.lib under Linux?

Or are there other reasons to cause the errors?
Thanks a lot
tony

__________________________________________________________________________
/*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,"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");
// This sentence can work. Just put it into the same directory as
invoke.cpp.

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

fprintf(stdout, "This is invokeSimplified4.\n");

jmethodID get_main_id;

if(cls != NULL)
{
    get_main_id =
env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
    fprintf(stdout, "This is invokeSimplified5.\n");

    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);
/*
        if (env->ExceptionOccurred())
        {
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
*/        fprintf(stdout, "This is invokeSimplified7.\n");
    }// end IF.

}// end IF.

jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}//end main.
______________________________________________________codes end.
Roedy Green - 30 Sep 2005 00:13 GMT
On 29 Sep 2005 15:19:01 -0700, tony_lincoln@yahoo.com wrote or quoted

>But how can I find the jvm.lib?
check out updatedb and locate.

It is one of the slickest features of linux. It is so fast.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

tony_lincoln@yahoo.com - 30 Sep 2005 15:06 GMT
What do you mean "updatedb and locate"?
Roedy Green - 30 Sep 2005 21:33 GMT
On 30 Sep 2005 07:06:42 -0700, tony_lincoln@yahoo.com wrote or quoted

>What do you mean "updatedb and locate"?

Are those not standard Linux commands?  I has been a while.  Look in a
bash manual.

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

tony_lincoln@yahoo.com - 01 Oct 2005 16:33 GMT
Yes they are. U r right. I should look a little bit more about the
manual. Sorry.
Tony
Gordon Beaton - 30 Sep 2005 08:34 GMT
> Under Linux, I tried to call java from C++ using JNI. The following
> is the C++ code which calls one java class named Menu_3D. When I
> compiled it using g++, there were many mistakes

I don't get the errors you report, but there are some things that need
to be fixed:

- main() must return int, not void.

- #include <windows.h> isn't necessary at all, remove it
 (anyway I suspect you don't have such a file on linux).

- normally you should include the system header files first, followed
 by jni.h and finally your own header files.

- the pragma is unknown to g++

After making the above changes, the code compiles fine using the
following commands:

(compile: invoke.cpp -> invoke.o)
 gcc -Wall -D_REENTRANT -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -c invoke.cpp

(link: invoke.o -> invoke)
 gcc -L $JAVA_HOME/jre/lib/i386/client invoke.o -lstdc++ -ljvm -lpthread -o invoke

(note that each of these two commands is exactly one line, even though
my newsreader or yours may have broken them)

To run the program you need to have the following directories in your
LD_LIBRARY_PATH:

 $JAVA_HOME/jre/lib/i386/client
 $JAVA_HOME/jre/lib/i386

/gordon

Signature

[  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

Roedy Green - 30 Sep 2005 09:22 GMT
>LD_LIBRARY_PATH

what is LD_LIBRARY_PATH? a system property, a SET environment
parameter? just a name for the path?  I was looking for signs of it
today earlier on my Windows machine. Nothing.  I vaguely recall seeing
it earlier..
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Gordon Beaton - 30 Sep 2005 09:38 GMT
> what is LD_LIBRARY_PATH? a system property, a SET environment
> parameter? just a name for the path?  I was looking for signs of it
> today earlier on my Windows machine. Nothing.  I vaguely recall seeing
> it earlier..

One of several enviroment variables that can be used to control the
dynamic linker/loader. They are described on the relevant man pages
(e.g. man ld.so on linux).

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 30 Sep 2005 14:57 GMT
Hi Friends and especially Gordon,

Thanks a lot for the words.  I did the following:
1.changed the path setting :
export
LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386/client:$JAVA_HOME/jre/lib/i386.
2. changed "void main()" into "int main()"

THen the erros are like this:
____________________________________________________________________
rakta:~/jniLinux$ gcc -Wall -D_REENTRANT -I $JAVA_HOME/include -I
$JAVA_HOME/include/linux -c invokeLinux.cpp
invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4' undeclared (first use this
  function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
  for each function it appears in.)
__________________________________________________________________________________

line 24 in invokeLinux.cpp is:
vm_args.version = JNI_VERSION_1_4;

Is there anything wrong with the version of JVM?
Thanks in advance.
tony
tony_lincoln@yahoo.com - 30 Sep 2005 16:28 GMT
When I remove this line,
vm_args.version = JNI_VERSION_1_4;

I can get invoke.o and invoke. But when I typed invoke, there is one
error:
error while loading shared libraries: libjvm.so: cannot open shared
object file: No such file or directory

I guess that is the problem about LD_LIBRARY_PATH. But I set it already
in bashrc file...
Why?
Gordon Beaton - 30 Sep 2005 16:40 GMT
> When I remove this line,
> vm_args.version = JNI_VERSION_1_4;

It sounds like you are using an earlier version of java - try using
JNI_VERSION_1_2, or check the value of JAVA_HOME.

What does "java -version" say?

> I can get invoke.o and invoke. But when I typed invoke, there is one
> error:
[quoted text clipped - 3 lines]
> I guess that is the problem about LD_LIBRARY_PATH. But I set it already
> in bashrc file...

LD_LIBRARY_PATH is what I'd check too. Where does JAVA_HOME point? Can
you find libjvm.so yourself somewhere in or below JAVA_HOME?

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 30 Sep 2005 16:53 GMT
I found two libjvm.so.
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/client/libjvm.so
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/server/libjvm.so
I know that they are different. But what is the difference?
Roedy Green - 30 Sep 2005 21:35 GMT
On 30 Sep 2005 08:53:55 -0700, tony_lincoln@yahoo.com wrote or quoted

>I know that they are different. But what is the difference?

there are two versions of java.exe and its attendant dlls.  You
control which one you get with the -server command line option.

The -server version is slower to start, but presumes it will keep
running the same code for a long time, so spends more time optimising
it.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

tony_lincoln@yahoo.com - 30 Sep 2005 16:52 GMT
I set the path like this:

export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/server/

This time I can compile it and got invoke.o and invoke. But when I type
invoke
then the new information comes:
Can't create Java VM

I really wonder why?
Gordon Beaton - 30 Sep 2005 16:55 GMT
> I set the path like this:
>
[quoted text clipped - 7 lines]
>
> I really wonder why?

You need to add *two* directories to LD_LIBRARY_PATH:

 /usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server
 /usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 30 Sep 2005 16:59 GMT
You are right. My java version is 1.4.2_05.
So I changed the codes into
vm_args.version = JNI_VERSION_1_4_2_05;

But the error kept the same:

rakta:~/GAQ$ gcc -Wall -D_REENTRANT -I
/home/gao/java/j2sdk1.4.2_08/include -I
/home/gao/java/j2sdk1.4.2_08/include/linux-c invokeLinux.cpp
invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
this
  function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
  for each function it appears in.)

:-(
Gordon Beaton - 30 Sep 2005 17:07 GMT
> You are right. My java version is 1.4.2_05.
> So I changed the codes into
[quoted text clipped - 12 lines]
> once
>    for each function it appears in.)

The only valid values are (AFAIK) JNI_VERSION_1_4, JNI_VERSION_1_2 and
JNI_VERSION_1_1, they are listed in jni.h.

The paths you mention in the example above don't agree with what
you've posted elsewhere, where you mentioned
/usr/lib/jvm/java-1.4.2-sun-1.4.2_05.

It seems you have several java versions installed. You need to make
sure you compile and link against the correct (and same) one.

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 01 Oct 2005 16:45 GMT
>It seems you have several java versions installed. You need to make
>sure you compile and link against the correct (and same) one.

I think that you are right. But how to cehck if I compile and link
against the correct java version?
I tried in different  computers, and it was the same: can not creat
JavaVM!
TOny
tony_lincoln@yahoo.com - 01 Oct 2005 17:57 GMT
I really thank Gordon Beaton and others a lot! Actually he showed me
already how to do it in his answers:
Just add one line in jni.h, to define JNI_VERSION as 1_4_2_08. Then I
can call java codes from C++ under Linux!
Thanks again for all the hints, especially the ones from Gordon Beaton!
tony_lincoln@yahoo.com - 01 Oct 2005 18:30 GMT
But still two quesions:

For the compiling and linking:
gcc -Wall -D_REENTRANT -I $JAVA_HOME/include -I
$JAVA_HOME/include/linux -c invoke.cpp
gcc -L $JAVA_HOME/jre/lib/i386/client invoke.o -lstdc++ -ljvm -lpthread
-o invoke

The parameters for gcc are really important. Without anyone of them,
the JNI calling can not work. But How do I know which parameter I
should choose?

Question two:
For the two libjvm.so,
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/client/libjvm.so
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/server/libjvm.so

I was told by Gordon that I should set the ID_LIBRARY_PATH like this:
 /usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server
  /usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386
But why?

Thanks a lot :-)
Gordon Beaton - 02 Oct 2005 09:39 GMT
> But still two quesions:
>
[quoted text clipped - 17 lines]
>    /usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386
> But why?

There are two versions of libjvm.so, a server and a client version,
and you need to link against one of them. I can't say exactly what the
difference is (some optimization details I think), but you can check
the documentation for the java command line options -server and
-client.

At runtime there are additional dependencies on library files found in
$JAVA_HOME/jre/lib/i386 (common to both server and client). So at your
library path needs at least two directories, the server (or client),
and the common one.

/gordon

Signature

[  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 - 02 Oct 2005 08:06 GMT
> I really thank Gordon Beaton and others a lot! Actually he showed me
> already how to do it in his answers:
> Just add one line in jni.h, to define JNI_VERSION as 1_4_2_08. Then I
> can call java codes from C++ under Linux!

Uhh, I don't recall suggesting you add your own JNI_VERSION to the
header file. My suggestion was to use one of the existing ones.

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 03 Oct 2005 17:43 GMT
No, u did not suggest that I should add my own JNI_VERSION to the
header file. It was my idea. But this idea was initiated by your and
other's words. Thanks a lot.
Tony
Owen Jacobson - 04 Oct 2005 06:34 GMT
On Mon, 03 Oct 2005 09:43:04 -0700, tony_lincoln wrote:

> No, u did not suggest that I should add my own JNI_VERSION to the
> header file. It was my idea. But this idea was initiated by your and
> other's words. Thanks a lot.
> Tony

Modifying library headers is almost never the right way to fix problems
using the library.  You're likely to introduce subtle bugs into your code
that way (eg., by using a constant value outside the expected range of
values).
tony_lincoln@yahoo.com - 04 Oct 2005 10:04 GMT
But in my library headers there is only:
#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002
There is no definition for JNI_VERSION_1_4 at all. As my current java
version is 1.4, I guess that I should add this new definition into the
header.
Another alternative is, to download a new jni.h which has the
definition for JNI_VERSION_1_4, I guess.
Am I right?
Chris Uppal - 04 Oct 2005 13:57 GMT
> But in my library headers there is only:
> #define JNI_VERSION_1_1 0x00010001
> #define JNI_VERSION_1_2 0x00010002
> There is no definition for JNI_VERSION_1_4 at all. As my current java
> version is 1.4, I guess that I should add this new definition into the
> header.

No definitely not, it means that you are looking at a version of jni.h that
does not belong to your jdk1.4.2 installation.  Find the right jni.h (it should
be in <jdk>/include/jni.h) and include that.

BTW, the numbers correspond to the version of the JNI spec, and do not relate
to the version number of the JDK in use.  For instance, in JDK1.5.0, the most
recent value of JNI version is still JNI_VERSION_1_4.

   -- chris
tony_lincoln@yahoo.com - 04 Oct 2005 10:11 GMT
a new question: how to call just one java method.
In the codes that I showed at the beginning, the c++ codes called the
main() method of java codes. Now the question is, how to call the
normal(not main()) method:
I tried like this (do_it is the java static void method that I would
like to call from C++):
...
jmethodID get_main_id;
jmethodID get_do_it_id;

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

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

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

These codes can be compiled and linked. But when I run it, there is
following error:
_____________________________________________________________________________________
Unexpected Signal : 11 occurred at PC=0x402B420F
Function=(null)+0x402B420F
Library=/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/client/libjvm.so

NOTE: We are unable to locate the function name symbol for the error
     just occurred. Please refer to release documentation for possible
     reason and solutions.
Current Java thread:
...
_______________________________________________________________________________

I guess that I used the wrong method in JNIEnv to call Java method?
tony_lincoln@yahoo.com - 04 Oct 2005 10:22 GMT
If I put the same parameter list in do_it() as in main(), that is,
String[] args, it can work.
But if the argument list in do_it() is not same as in main(), what is
the correct code?
Gordon Beaton - 04 Oct 2005 10:44 GMT
> If I put the same parameter list in do_it() as in main(), that is,
> String[] args, it can work.
> But if the argument list in do_it() is not same as in main(), what is
> the correct code?

Regardless of what arguments do_it() needs (i.e. either the same as
main() or different), you need to pass the correct signature to
GetStaticMethodId(), and you need to create the correct type of
argument for the call. Be more specific if this doesn't answer the
question.

/gordon

Signature

[  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 - 04 Oct 2005 10:46 GMT
> Unexpected Signal : 11 occurred at PC=0x402B420F

If either of the calls to GetStaticMethodID() fails (leaving NULL in
the correspoding id variable) then you are not free to continue
calling JNI functions until you clear the pending exception.

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 30 Sep 2005 17:03 GMT
Yes. I changed the path into:

rakta:~/GAQ$ export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386

Then compile it, and the error kept the same:

invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
this
  function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
  for each function it appears in.)

If I remove the line "vm_args.version = JNI_VERSION_1_4_2_05",
I can compile it, but the final result kept the same:
"Can't create Java VM"

Sorry for my questions.
Gordon Beaton - 30 Sep 2005 17:09 GMT
> Yes. I changed the path into:
>
> rakta:~/GAQ$ export
> LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386
>
> Then compile it, and the error kept the same:

LD_LIBRARY_PATH has nothing to do with compiling the code. It's only
there to help find the libraries that are needed when you *run* the
program.

> invokeLinux.cpp: In function `int main()':
> invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
[quoted text clipped - 7 lines]
> I can compile it, but the final result kept the same:
> "Can't create Java VM"

I've responded to this in another post. This JNI_VERSION isn't valid.

/gordon

Signature

[  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

tony_lincoln@yahoo.com - 30 Sep 2005 17:14 GMT
Thanks. I think that you are correct. I will try to compile and link
against the correct (and same) version tomorrow.
Thanks a lot and Have a nice weekend.
tony
Jeff Schwab - 30 Sep 2005 15:35 GMT
>>LD_LIBRARY_PATH
>
> what is LD_LIBRARY_PATH? a system property, a SET environment
> parameter? just a name for the path?  I was looking for signs of it
> today earlier on my Windows machine. Nothing.  I vaguely recall seeing
> it earlier..

LD_LIBRARY_PATH is an environment variable used to tell some linkers
where to look for libraries.  I have found it useful with the GNU tools
on various flavors of Unix.
James McIninch - 03 Oct 2005 04:46 GMT
<posted & mailed>

It's not likely that the Linux code will need the Windows JVM library. Why
not use the Linux one. The errors also indicate that you didn't include
jni.h, including the headers might be helpful too.

> Dear Friends,
>
[quoted text clipped - 112 lines]
> }//end main.
> ______________________________________________________codes end.

Signature

Remove '.nospam' from e-mail address to reply by e-mail



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.