JNI: Debugger

M

M. Fernandez

Hello,

I have terrible bug in my JNI code and I would like to use a debugger
such as the debugger of Eclipse (for java) or the VC++. However, because
it is a JNI code, I don't know how to "see" my java and c++
variables/objects.

Do you have any idea/program that may help me ??

thanks a lot,

Marcelo
 
G

Gordon Beaton

I have terrible bug in my JNI code and I would like to use a
debugger such as the debugger of Eclipse (for java) or the VC++.
However, because it is a JNI code, I don't know how to "see" my java
and c++ variables/objects.

Do you have any idea/program that may help me ??

I don't know about Windows debuggers, but maybe this general info will
help...

- compile your native lib with debugging info

- start java under control of a native debugger.

- set a breakpoint in one of your native methods

It can be tricky getting the debugger to see dynamically loaded code
(especially if you need to start your application and load the library
before setting the breakpoint), this is a workaround that may be
easier:

- write a java launcher in C (or use the one included in the src.zip
that comes with the JDK).

- statically link your native methods in the launcher (i.e. don't
build a shared library or DLL). Make sure debugging info is turned
on when you compile.

- temoporarily comment out System.loadLibrary() from your
application (loading isn't necessary when your methods are already
in the executable).

- run your launcher in the native debugger.

/gordon
 
C

Chris Uppal

M. Fernandez said:
I have terrible bug in my JNI code and I would like to use a debugger
such as the debugger of Eclipse (for java) or the VC++. However, because
it is a JNI code, I don't know how to "see" my java and c++
variables/objects.

I don't know of any really good way of doing this, but you should be able to
get part of the way there by using both debuggers at the same time. Basically,
the idea is that you start your Java program under Eclipse, and then tell VC to
attach to the running process too.

Alternatively, you could do it the other way around, run the program (java.exe)
under VC with your debug DLL, and tell Eclipse to attach to that running
program.

I admit I haven't tried either approach, but I can't think of any reason why
they should not work. I think the first one would be less fiddly. If you
need help on attaching to a running process then ask again.

Once that's working (if it does!) then you've be able to "see" objects on both
sides of the JNI interface. Since, at any one time, either Eclipse or VC will
think the code is "running" (not at a breakpoint), you'll have to take more
notes than you normally would, in order to keep the connection between objects
and JNI handles clear. So it'll be pretty tedious, but it should be manageable.

Another approach would be to use something like Jace,
http://sourceforge.net/projects/jace
to generate complete wrappers for your Java classes. You could then (in so far
as the VC debugger allows it) "see into" the Java objects using C++ code. That
sounds rather elaborate, and might easily not pay for itself, but it's worth
thinking about. If you do try it and it works[*] then please let us know ;-)

-- chris


[*] I know that it /could/ work because I have a similar -- but more dynamic --
system with Smalltalk talking to Java via the JNI API. With it the Smalltalk
debugger and inspectors can "see" right into Java objects just as if they were
Smalltalk[**] -- so it is possible ;-) The principle limitations are C++ and
the VC debugger, not Java or the JNI barrier itself.

[**] They can see in, but they can't, say, step into Java code any more than VC
could. However I can play the same "two debuggers" trick, if I need to -- and
I have needed to once or twice.
 
M

M. Fernandez

Hi,
thank you very much your help, but i don't know how o attach (eclipse or
VC) to a running process. How can I do it?

thanks a lot,

Marcelo
 
T

Thomas Fritsch

M. Fernandez said:
Hi,
thank you very much your help, but i don't know how o attach (eclipse or
VC) to a running process. How can I do it?
Attaching an debugger (like the one of eclipse) to a running process is
called "remote debugging".
For how to start a debuggable remote java process: see for example
<http://groups.google.de/[email protected]>.
For how to attach the Eclipse-debugger to it: From Eclipse's menu open
"Run" -> "Debug..." -> select "Remote Java Application".
 
C

Chris Uppal

M. Fernandez said:
thank you very much your help, but i don't know how o attach (eclipse or
VC) to a running process. How can I do it?

OK, here we go. It helps to be sober and alert when you do this...

===========

To attach to a running process using VC (this is Visual Studio 2003 specific,
the details are slightly different (simpler) using VC 6).

In VS. Compile your DLL for Debug (obviously!). Move the .DLL to wherever
your java application expects to find it. Set a breakpoint in your C++ code.

Now, go to your Java code. Ensure that it is a long running application, so
that it does not just startup and immediately exit. If necessary add:
System.out.println("Press return");
System.in.read();
to your main() to make it pause until you are ready. Now start the Java
program. At this stage /don't/ use Eclipse to do this, use the command line.

Go back to VS. Under the "Debug" menu, select "Processes...". In the new
process window, scroll down to java.exe, select it and press the attach button.
A prompt will come up to check what kind of program it is, it should be set
correctly (Native). Press OK. Close the "Processes" window (it just gets in
the way). Now you may see that your breakpoint has changed to show a '?'. If
so that's because Java hasn't loaded your DLL yet, if it already has, then your
breakpoint will look normal.

Go back to your app, and let it advance to the point where it uses your native
code. You should see the process stop at your breakpoint. Most of the stack
will consist of functions in the jvm.dll, but the top function should be your
JNI code.

When you've finished debugging, select Debug=>Detach all (or use the Processes
window again), or you'll kill your Java application.

===========

To attach to a running process using Eclipse (you probably won't need this
bit -- I've just put it in for completeness).

Start Eclipse (go get a cup of coffee while you wait). There's probably a way
to tell Eclipse to debug using classfiles and source that is stored elsewhere,
but I can't be bothered to find out what it is. And you've probably got all
your Java code in Eclipse already....

Set whatever breakpoints you want in Eclipse.

Set up a remote debug definition. Select "Run=>Debug..." and then create a new
debug def under "Remote Java Application", set the source if necessary (just
like a normal debug def). Chose the default connection type ("Standard (socket
attach)"). Make a note of (and change if you want) the TCP/IP port that it
will connect to -- it defaults to 8000 which may already be in use on your
machine.

Now start your Java application from the command line. It'll be a line like:

java
-cp .
-agentlib:jdwp=transport=dt_socket,address=localhost:8765,server=y,susp
end=n
MyClass arg1 arg2

(I've put it on several lines, and used no quotes -- depending on which command
line processor you use, you will have to change the details)

The -cp points to wherever Eclipse has put your compiled class files.

The next line breaks down as follows (options are detailed in the JMVTI/JPDA
documentation, see
http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html ):

-agentlib:jdwp=
This tells java to start the debugging agent (which Eclipse will
connect to)
The rest of the string is a comma-separated list of options for the
agent.

transport=dt_socket
This says to use TCP/IP sockets to talk to the debugger.

server=y
This says to set up a socket waiting for the debugger to connect to the
java process (instead of the java process connecting to a waiting
debugger).

suspend=n
This says not to wait for the debugger to connect before starting. I'm
assuming that you don't want to wait.

address=localhost:8000
This says which host/port to listen for connections on, and should be
the same as you told Eclipse.

That will start your Java application. Now go back to Eclipse, and activate
your new remote debug definition[*]. Eclipse should now connect to your
application (nothing much shows in the GUI). Go back to your application and
allow it to progress to the breakpoint you set about 3 pages ago. Eclipse
should stop it, and you'll have the normal debug view of the "remote"
application.

===========

To do both at once. You could just do both of the above at once. But it's
easier to start the application under the normal (not remote) Eclipse debugger
without messing with all the command-line stuff. Once it has started, and got
to an Eclipse breakpoint, go to VS, and attach to the running process as
before. You will have to guess which javaw process to attach to. On my
machine now, there were two instances of javaw.exe running, one with a "Title"
of something like "Debug <something> Eclipse SDK", and the other with no title
at all. It's the one with no title that you want (though I don't think it'd
harm to attach the other too). Now (in Eclipse) allow the process to advance
to the VS breakpoint you set in your JNI code. VS, will trap that and come to
life. Eclipse, meanwhile, thinks the application is running normally ("not
responding"), and is not halted at a breakpoint. By advancing between
breakpoints set in either domain, you can debug through an entire JNI call.

Have fun!

/Then/ go get a beer -- you'll need it...

-- chris
 
M

M. Fernandez

Chris said:
M. Fernandez said:
thank you very much your help, but i don't know how o attach (eclipse or
VC) to a running process. How can I do it?

OK, here we go. It helps to be sober and alert when you do this...

===========

To attach to a running process using VC (this is Visual Studio 2003 specific,
the details are slightly different (simpler) using VC 6).

In VS. Compile your DLL for Debug (obviously!). Move the .DLL to wherever
your java application expects to find it. Set a breakpoint in your C++ code.

Now, go to your Java code. Ensure that it is a long running application, so
that it does not just startup and immediately exit. If necessary add:
System.out.println("Press return");
System.in.read();
to your main() to make it pause until you are ready. Now start the Java
program. At this stage /don't/ use Eclipse to do this, use the command line.

Go back to VS. Under the "Debug" menu, select "Processes...". In the new
process window, scroll down to java.exe, select it and press the attach button.
A prompt will come up to check what kind of program it is, it should be set
correctly (Native). Press OK. Close the "Processes" window (it just gets in
the way). Now you may see that your breakpoint has changed to show a '?'. If
so that's because Java hasn't loaded your DLL yet, if it already has, then your
breakpoint will look normal.

Go back to your app, and let it advance to the point where it uses your native
code. You should see the process stop at your breakpoint. Most of the stack
will consist of functions in the jvm.dll, but the top function should be your
JNI code.

When you've finished debugging, select Debug=>Detach all (or use the Processes
window again), or you'll kill your Java application.

===========

To attach to a running process using Eclipse (you probably won't need this
bit -- I've just put it in for completeness).

Start Eclipse (go get a cup of coffee while you wait). There's probably a way
to tell Eclipse to debug using classfiles and source that is stored elsewhere,
but I can't be bothered to find out what it is. And you've probably got all
your Java code in Eclipse already....

Set whatever breakpoints you want in Eclipse.

Set up a remote debug definition. Select "Run=>Debug..." and then create a new
debug def under "Remote Java Application", set the source if necessary (just
like a normal debug def). Chose the default connection type ("Standard (socket
attach)"). Make a note of (and change if you want) the TCP/IP port that it
will connect to -- it defaults to 8000 which may already be in use on your
machine.

Now start your Java application from the command line. It'll be a line like:

java
-cp .
-agentlib:jdwp=transport=dt_socket,address=localhost:8765,server=y,susp
end=n
MyClass arg1 arg2

(I've put it on several lines, and used no quotes -- depending on which command
line processor you use, you will have to change the details)

The -cp points to wherever Eclipse has put your compiled class files.

The next line breaks down as follows (options are detailed in the JMVTI/JPDA
documentation, see
http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html ):

-agentlib:jdwp=
This tells java to start the debugging agent (which Eclipse will
connect to)
The rest of the string is a comma-separated list of options for the
agent.

transport=dt_socket
This says to use TCP/IP sockets to talk to the debugger.

server=y
This says to set up a socket waiting for the debugger to connect to the
java process (instead of the java process connecting to a waiting
debugger).

suspend=n
This says not to wait for the debugger to connect before starting. I'm
assuming that you don't want to wait.

address=localhost:8000
This says which host/port to listen for connections on, and should be
the same as you told Eclipse.

That will start your Java application. Now go back to Eclipse, and activate
your new remote debug definition[*]. Eclipse should now connect to your
application (nothing much shows in the GUI). Go back to your application and
allow it to progress to the breakpoint you set about 3 pages ago. Eclipse
should stop it, and you'll have the normal debug view of the "remote"
application.

===========

To do both at once. You could just do both of the above at once. But it's
easier to start the application under the normal (not remote) Eclipse debugger
without messing with all the command-line stuff. Once it has started, and got
to an Eclipse breakpoint, go to VS, and attach to the running process as
before. You will have to guess which javaw process to attach to. On my
machine now, there were two instances of javaw.exe running, one with a "Title"
of something like "Debug <something> Eclipse SDK", and the other with no title
at all. It's the one with no title that you want (though I don't think it'd
harm to attach the other too). Now (in Eclipse) allow the process to advance
to the VS breakpoint you set in your JNI code. VS, will trap that and come to
life. Eclipse, meanwhile, thinks the application is running normally ("not
responding"), and is not halted at a breakpoint. By advancing between
breakpoints set in either domain, you can debug through an entire JNI call.

Have fun!

/Then/ go get a beer -- you'll need it...

-- chris

Merci beaucoup!!

Thank you very much, this was really useful and well-explained. Now I
can debug my horrible JNI program.

thanks a lot,

Marcelo
 
M

M. Fernandez

Hello,
I do really appreciate the answer given in this newsgroup. However, I
still have some problems with the VC++ debugger with the JNI.

1.- Launch the java application on the command line (long process
System.in.read).
2.- Attach VC++ debugger to the java.exe process.

3.- Set a breakpoint in the cpp code. Here, I have a problem attaching
the process because VC++ shows me a "not normal debug icon" (with an
important sign to it). It seams that the library msvcm80d.dll (message:
Using symbol files from an unkwon or untrusted location can be harmful
to your computer). With this problem, the debugging doesn't work.

Do you have an idea about what I am doing wrong?

Thanks a lot,

Marcelo

PS: With Eclipse, it works perfectly with the remote debugging or by
using the TCP/IP connexion for debugging.
 
M

M. Fernandez

M. Fernandez said:
Hello,
I do really appreciate the answer given in this newsgroup. However, I
still have some problems with the VC++ debugger with the JNI.

1.- Launch the java application on the command line (long process
System.in.read).
2.- Attach VC++ debugger to the java.exe process.

3.- Set a breakpoint in the cpp code. Here, I have a problem attaching
the process because VC++ shows me a "not normal debug icon" (with an
important sign to it). It seams that the library msvcm80d.dll (message:
Using symbol files from an unkwon or untrusted location can be harmful
to your computer). With this problem, the debugging doesn't work.

Do you have an idea about what I am doing wrong?

Thanks a lot,

Marcelo

PS: With Eclipse, it works perfectly with the remote debugging or by
using the TCP/IP connexion for debugging.
Sorry for this question,

The problem is not related to the method described in this thread.
Actually the problem is about Nero 6 and the DirectShow filters.
A thread that may be useful can be found
http://www.atrevido.net/blog/CommentView.aspx?guid=68ff8e49-8bd7-4c34-94bc-15145270ecbc

another problem may be ACDSee, but i cannot prove it.

Marcelo

PS: I have uninstalled Nero PhotoSnap and similar programs. And I have
unregister some programs that were using the DirectShow filters. A tool
that may help you can be found on
http://www.free-codecs.com/RadLight_Filter_Manager_download.htm
 
C

Chris Uppal

M. Fernandez said:
The problem is not related to the method described in this thread.
Actually the problem is about Nero 6 and the DirectShow filters.

Eek!

I'm glad you found the problem. I, for one, would never have thought of
anything like that.

-- chris
 

vvl

Joined
Sep 18, 2007
Messages
1
Reaction score
0
Hello
You can try our Eclipse* based tool for debugging Java*/JNI environment that uses CDT and JDT perspectives makes developer works comfortable for Eclipse* users and moving out two debugger scenario to the history.
Please find time to visit http://softwarecommunity.intel.com/articles/eng/1435.htm and try it. Let us to know if it helps to you or not, and what changes should be done to meet your expectations and requirements.

--
Vasily v. Levchenko
Senior Software Engineer
Intel(R) Corporation
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top