debugging multi process java applications - java

What is a good system for debugging a multi process Java application where it isn't clear which process should be debugged?
For example, in Python I can use rpdb and add the line import rpdb; rpdb.set_trace() so execution blocks until I connect to the debugger with e.g. nc 127.0.0.1 4444.
Compared to the above quick and reliable method, when I'm using a Java debugger, I see the following challenges:
Ensure that every process is run with proper arguments to allow debugging -- in my case it isn't clear what is starting all the processes so it isn't obvious where to change the arguments. Is there a way to change the defaults on my computer to always include the jvm options -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044?
Decide what process to connect the debugger to before the desired code is hit -- again, it isn't clear which process I should connect to, and it is convenient that rpdb blocks until the debugger connects and you don't need to identify the process id. Is there anything similar to this in Java?

Start java with something like:
java -agentlib:transport=dt_socket,server=y,suspend=y,address=1044
The suspend=y bit tells the VM to wait until a debugger connects before running main(). address is the port to connect to.

Related

Eclipse: Java Monitor won't show cpu statistics

I am profiling a java application using jvisualvm. The CPU profile from jvisualvm has narrowed down the slow part of the code to one particular method. It doesn't say which part of the method is slow though.
To get more information I tried debugging through Eclipse using Java Monitor (available through Eclipse Marketplace). Java Monitor will attach to the application but it won't display CPU statistics. I don't know why. I have modified the JVM options using:
-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y
Then I create a profile in Eclipse using:
Remote Java Application > myapplication
Here I select the source code for the project I am profiling. I start the application and it waits for the debugger to attach:
Listening for transport dt_socket at address: 8000
I right click the PID under local host and click 'Start Monitoring'
Then in Eclipse I press F11 to kick off the application. It starts running, but under 'Properties' I get everything except CPU. Any ideas greatly appreciated..
I don't know any Java profiler which can tell you which part of a method eats most of the time. If you can't tell by looking at the method, then your method is probably too big to understand anyway. Try to refactor it into several methods.
If you have lots of local variables, use a worker object and turn local variables into fields of the worker. That way, you can avoid writing methods with a dozen parameters and still cut a overly complex method to size.
As for why Java Monitor doesn't do what you want: You need to tell it which packages to monitor and which profiling method to use. See the documentation for details.

Start/stop java application from an external script

I have a Stand-alone Java application. At the moment I am running this Java application using a start-script i.e. startApplicatoin.bat in windows and startApplicatoin.sh in Linux which sets up the class-paths and then it executes: java -classpath .
Now I have to add a stopApplication.bat and stopApplication.sh script. This stop script has to shutdown/close this java application gracefully.
To achieve this I am planning to take the following steps:
1. When my java application runs it will store the process-id of the launched application in a file i.e. in a known file myapplication.pid.
Looks like ManagementFactory.getRuntimeMXBean().getName() call will work on both Linux and Windows to get the process ID. So I shall collect process ID in this way and will store it in the specified file myapplication.pid.
2. Then when running stop application script, this script will issue a “kill” request to the process-id as specified by that myapplication.pid file.
For Windows I shall run the "taskkill" command to stop this application. And for Linux environment "kill" command will serve that purpose.
And in my java code I shall add a addShutdownHook which will enable the graceful shutdown operations that I want to run i.e. there I shall handle whatever stuffs I want to persist before this program is going to stop.
http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#addShutdownHook%28java.lang.Thread%29
Now I would like to do a sanity check to ensure the way I am thinking is the proper way to do. Or there is a better way to do this. Any suggestion is appreciated. And thanks in advance.
If you're wanting a "graceful" shutdown, it may be more practical (and easier cross-platform) to open a socket in your long-running process and have your "stop" script connect to it and issue a shutdown command; this might even be practical through JMX, depending on how your application overall is structured. Approaches that are "inline" rather than requiring interaction with the OS are generally easier to reason about and test.
This looks like a Daemon.
The easiest way to run a daemon with start/stop functionality without resorting to a lot of scripting is with jsvc. This allows your code to implement an interface with four methods:
void init(String[] arguments): Here open configuration files, create a trace file, create ServerSockets, Threads
void start(): Start the Thread, accept incoming connections
void stop(): Inform the Thread to terminate the run(), close the ServerSockets
void destroy(): Destroy any object created in init()
You then have platform specific binaries that deal with keeping track of the process and stopping it when requested to do so.
The most useful thing is that jsvc can start a process as a superuser (root on unix) and then drop to a peon user the for auction running of the process.
This is how Tomcat (for example) works, it starts as root and performs privileged actions such as binding to port 80. It then drops down to a peon use called tomcat for security reasons.

How can you find out if a Java program failed on a Linux server?

I was running a big overnight batch program last night written in Java on a Linux based server. I can't seem to find anything in my error logs that suggests an error was encountered in my Java application.
Is there a way in Linux to see if a program exited unexpectedly?
The program is one of many programs that get run overnight off a chronjob/tab and runs off its own main method. It catches a series of exceptions which prints messages to System.err.println and exits with status one if these are hit.
NB: I always use a Logger in my code unfortunately I'm dealing with legacy code written by someone else.
If Java crashed there will be a hs_err_pid????.log file in the working directory of the application by default. (This is unlikely to be the case)
If the application logged an error before exiting, you need to understand where your application places its logs and read those (as they can be anywhere on your system)
There's no easy mechanism to discover what you're after, if whatever tool you used to start the java JVM didn't bother recording the exit status for you.
If you're running the auditd(8) server to provide audit logging, and your auditd(8) is configured to log abnormal exits and your java JVM exited abnormally -- signal-based termination -- then you can look for ANOM_ABEND events in /var/log/audit/audit.log:
# ausearch -m ANOM_ABEND
/sbin/audispd permissions should be 0750
----
time->Tue Nov 8 18:42:22 2011
type=ANOM_ABEND msg=audit(1320806542.571:264): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=11955 comm="regex" sig=11
...
For future executions you might want to do something like this:
java /path/to/whatever.jar && echo `date` >> /path/to/dir/success || echo `date` >> /path/to/dir/failure
This will echo the date of success or failure into a log file -- assuming that your application uses the standard Unix-style exit(0) for success and anything else for failure.
Because you've run your programs out of cron(8), there's a good chance that the standard error of the program has in fact been captured and mailed somewhere.
Check the crontab(5) for the user account that runs the program. (If it is run out of /etc/crontab or /etc/cron.d/, then in those files.) Look for the MAILTO variable. If it doesn't exist, then cron(8) tried to deliver mail to the crontab(5) owner. If it does exist, then cron(8) tried to deliver mail to whoever is specified with the variable.
Look in /var/spool/mail/ for the user's mailbox, if the server doesn't seem like it's got an email setup in place -- there might be enough for local delivery.
it is the virtual machine process (named java) whose termination status you want to check. you can write a trivial script with 2 commands, the first invokes the java vm to run the java program and the second records the exit status: echo $?
If you did write the application, you should use a logger that writes to a file.
See this tutorial how to use Log4j with a file appender. In your code, you need to catch and log exceptions.
See this issue.

How to up an aplication on remote linux and wait for answer

Someone can tell me the best way, through a web Java application, how to run an application on a remote machine (linux) and how to know if this application has already completed. I know the application terminates automatically, so just wanted to wait for the answer.
any help or advice are very welcome.
I was confused by the wording, so I will assume the following: the web application and the remote application are running on two different machines, with the remote application on Linux.
If that is the case, then you would be better off using a SSH library for Java (there are several - JSch, sshj, Ganymed SSH-2, to connect to the remote machine and run commands on it. This is a better approach than using ProcessBuilder, for it abstracts you from the problem of providing your password to the terminal (which can get quite tricky).
I'm not sure what you meant by this statement: "I know the application terminates automatically, so just wanted to wait for the answer." so I'll make another assumption that you want to know if the remote process terminated successfully or not. I'm unsure if any of the SSH libraries posted above, will allow you to get the remote process status in a non-trivial way, so you are better off writing a shell wrapper to your remote command that will return a parseable message.
If you are running both on the same machine, use ProcessBuilder.

Debugging Java Application Over Network

I have a core java app running on a computer on my network. Can I attach a debugger (netbeans preferred) to this from another computer on the same network?
Please advise how to do this if it is possible, or point me to an article I've had a terrible time googling for it. I don't see why it shouldn't be possible.
Thanks
Yes, you can.
Start your JVM with these arguments:
-Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=n
The address number is the port number the JVM will listen on for a debugger to attach to. Set suspend to y if you want the JVM to wait until a debugger is attached before starting main.
Your debugger should have the option to connect to a remote JVM. It should be a simple matter of punching in the host and port number.
I assume you mean a java app run from the CL by "core java"? If so
What are Java command line options to set to allow JVM to be remotely debugged?
Once you tell the jvm to listen on a port, just point your netbeans debugging profile to the machine ip and port. This should be very doable.

Categories

Resources