Tracking java exceptions by hooking into the JVM [duplicate] - java

Is there a way to log all exceptions happening within JVM?
A system is built from a big number of smaller components provided by different groups. All of them are running within the same JVM (under Weblogic).
Error reporting policies are rather different in those groups, so sometimes we have cases of suppressed exceptions, which makes troubleshooting very hard. At the same time, I noticed that JDB is able to intercept any exception happening in the code, no matter where.
I'd like to use the same facility JDB uses in DEV/SIT/UAT environment to shorten issue resolution time. In PTE and PROD though the facility shall not only be turned off, but
create no performance impact
require no code change for turning it off.
Of course, I can have JDB connected to every instance of server running in DEV/SIT. It's feasible, I guess... but there are two main downside:
it makes configuration more complex
JDB stops when an exception has occured; need a script or something to let it continue
So I wonder is there any method that does it, e.g. Runtime.traceExceptions(...)?

As far as I know there is no official Java API for this besides the debugging API which could be used also from inside the VM that is about to be 'debugged'.
An easier quick and dirty way to get notified of every exception that is created at runtime is to hack some tracing code directly into the constructor(s) of the Throwable class, compile it and put it into the bootclasspath before the rt.jar. This is of course nothing you should do in a release version but it can be very helpfull to analyse code that catches exceptions somewhere and doesn't report them properly.
In response to the comments:
Regarding the Debugger API: The last time I did something like this I used the JVMDI to build a native JNI/JVMDI dll and accessed it from inside the VM. It works and lets you do all sorts of wired things that Java normally doesn't offer but I would consider this even more of a hack than using a patched Throwable class. Besides that, the JVMDI has been deprecated and was replaced with JVM TI since Java 1.6. I don't know if and how you can do something like this with this new Debugger API as well.
Using a modified Throwable is fast, easy to get right, doesn't impose any performance degeneration by itself and also not even really hackish if you are in control over the execution environment. You could think of as some kind of AOP. ;) But I would still only use it to find otherwise hard to detect bugs and not in production code or only as a last resort. Something like this should surely not be considered as part of the design. The best long term approach would be to get all your development groups to agree on some common exception treatment.
Also FindBugs can help a lot if you decide to do a code review to find all these spots where exceptions get caught and not reported.

I would probably un-jar the JDK, modify "Exception" to log your exception and then re-jar it.
It's a pretty reasonable solution and won't cause any problems--the JDK classes are, for the most part, just standard java classes.
You might be able to do it without modifying the JDK by manipulating the class path to read your version of "Exception" before reading the JDK's version--that way it wouldn't be as difficult to distribute.

GDB is designed for GCC built programs, If you are debugging a Java application I suggest you use the Java Debugger in your IDE. It can be used to trap any exception thrown.
Note: some of the libraries throw exceptions during start up normally and imagine Weblogic has some of its own.

There's a project on Fedora - ABRT - automatic bug reporting tool.
It also reports uncaught JVM exceptions.
Right now (2013), an effort is started to make it also catch JBoss AS / EAP / WildFly exceptions.
Stay tuned to know when it comes: https://fedorahosted.org/abrt/milestone/Support_for_JAVA_exceptions

Related

way to debug java frameworks on console

I am a C++ dev, working in java technology for about a year. Forgive my ignorance, but I have tried to search for following two questions.
What is the best way to debug in console for a java application (ala gdb in good ol' C++).
It seems jdb is below par.
Eclipse is the way to go for its IDE. But Eclipse is a GUI and I do develop in console on unix servers.
What is the best way to tame huge jave open-source frameworks. eg, camel, hibernate, spring, logback, blah, blah
I do most of my debugging in the console.
I have found that for the majority of bugs, Java stack traces are sufficient to identify the bug and develop a fix. This of course means that it's critical to allow stack traces to be seen on the console. For most applications, I've found that it's best to allow unchecked exceptions to propagate until they terminate the thread, with a stack trace showing up in the console; unchecked exceptions should normally indicate programming errors or uncontrollable conditions where the thread should be terminated anyway.
In cases where the stack trace is not sufficient, I've found that using System.out.println() during the debugging process is actually more effective than using an interactive debugger. Having a full log of a run is for me more useful than running a debugger where I may easily step past an issue that later turns out to be important.
Wat is the problem in setting up the project in eclipse IDE, you can always get the source code and set up your workspace??
Using sysout is great for small java programs but as the code grows or for big application (according to my understanding you plan to debug something big :P) it would really be a headache placing all those sysout and then removing them once you are done with the debugging.
I would suggest you to set up your own workspace by choosing 'import existing project in workspace' option of IDE, though it would be tiring first but will help you in long run.
I would say that there is no need for such a tool, because Java supports remote debugging.
You need to start your (server) JVM with remote debugging enabled - this will work for newer JDKs:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
After that you connect to it from the IDE, and set breakpoints or conditional breakpoints wherever you like.
See this question for more details
Also, this is a personal preference, but I would say that IntelliJ IDEA is the way to go as far as Java IDEs go.

Upgrading from Java 1.4 to JAVA 6 SE

I am currently upgrading from JAVA 1.4 to JAVA 6 SE. Some of the methods and classes have either been deprecated or there are a lot of warnings due to inefficient practices. I want to know if it is possible for me to upgrade without making any changes to my code and after the changes remote debug to fix the errors. If there's a simpler or more efficient way of doing this please share.
The usual approach is:
Run your code through the new compiler
Fix any compile errors (might happpen in some rare cases, like when you used the word enum as identifier, which is a keyword for Java 1.5 and greater)
Do a full QA cycle to verify that your application still works properly
Besides that, you should consider upgrading to Java 7 - Java 6 is also already in its end-of-life phase.
I want to know if it is possible for me to upgrade without making any changes to my code and after the changes remote debug to fix the errors.
We can't give you a definitive yes or no to that.
First, it should be noted that most of the deprecations and warnings can be ignored to start with. (Some are telling you about things that should be fixed soon, but the most egregious examples of bad / dangerous APIs were deprecated long before Java 1.4)
So one reason we can't give you a definitive answer is that we don't know what warnings you are seeing (duh!).
The other reason is that we don't know how good / extensive your test suite is. If you have a good test suite, the chances are good that any problems will be picked up. If not, or if you are relying on manual testing, then your chances of finding any problems cause by the upgrade are greatly reduced.
The other thing to note is that the documentation for each major Java release includes a section on Incompatibilities between the new release and the previous one. It is a good idea to at least skim these documents to see if any of the issues highlighted are likely to impact on your application.
Finally, most people find that upgrading doesn't result in a large swath of problems. There are exceptions of course. And if you are in the habit of depending on implementation specific behaviour rather than what the javadocs say, THAT can lead to pain.
Basically, you can run your Java 1.4 code on a Java 6 virtual machine without modifications. New API's might have been introduced, effectively deprecating old ones. Usually, the Javadoc of the deprecated API should give you a pointer what you should use instead.

Is it normal for java library code to throw & catch lots of exceptions during "normal" processing?

More as an experiment, I decided to enable the following breakpoint in the Eclipse debugger: Throwable [Include Subclasses]: caught and uncaught. I then let my code (which is running "fine" as far as I know) run under the debugger, and was surprised to see dozens of exceptions being thrown and caught (previously unknown to me) by standard J2SE library code when my code was running normally for all I know.
For example, here are just some of the Java framework functions I found throwing exceptions: URLClassLoader.findClass, FileDirContext.lookup, and WebappClassLoader.findClassInternal.
Is this considered normal behavior for a Java application? Is this something I should look into? My code seems to be running fine as far as I know.
Though it is bad to design your code in this way (exceptions are slow, and should be used for exceptional circumstances), Bhesh Gurung's comment is the right way to think about this. Follow the specification of the code you are relying on, and don't worry about the implementation.
Exceptions thrown during class-loading are relic from early days in Java history when class loading was designed to use them as a way how to communicate that some class-loader was not able to find a class. It is not considered to be a good pattern now but it remains there and probably won't be changed ever as it is part of APIs. Nothing to be scared of.

Update Java code during runtime

about a year ago I stumbled across a nice feature in Java that I cannot for the life of me find again.
Through some magic interface it was apparently possible to declare some classes or functions replaceable during runtime.
I found a nice example guide of someone who ran a simple little program that printed a certain message, he then updated the program using a method I cannot remember anymore and all of a sudden the program had replaced that old print function with a new one.
I've tried looking through the Java API to spark my memory as well as googling but without success. Can anyone here help?
Various app containers can do this.
Basically you'd need to reload the class in a new ClassLoader (unless you're talking about doing this under the debugger, in which case there are completely different APIs available).
In my opinion, this kind of thing is rarely worth the hassle: designing everything so that it can be reloaded is considerably harder than designing it so it can be completely restarted in a new process. It's also easier to be sure exactly what code is running if there's only ever one version loaded in the process.
It's a neat thing to be able to demo, but for most applications it's not worth it. All in my opinion, of course :)
Note that one notable exception is the ability to reload web UI layers without restarting the container: that can make life much easier.
The HotSwap technology was added to Java 1.4 and enable class file replacement at run-time. The feature is provide through the redefineClasses method of the instrumentation package. I think you can also do that through the JPDA interface.
Here is also a reference to what I believe is the research paper that describe the HotSwap mechanism first:
Towards Flexible and Safe Technology for Runtime Evolution of Java Language Applications
Otherwise you can use Classloader, as the other mentionned, but it only provides dynamic class loading, not replacement. The same class loaded twice will be considered as two different types. Combined with interface and/or a bit of reflection, it can however provide ways to update the application at run-time.
Here is a reference to an awesome paper about class loader, and there usage:
Dynamic Class Loading in the Java Virtual Machine
I won't expand on whether this is good or bad, because it was not your question, but I think it's great to have support for run-time software evolution -- too bad that JSR-117 never made it!
This is typically the kind of functionality I gladly leave to infrastructure as it is difficult to get right and easy to get wrong. As Jon mentioned above, most applications do not need it and for those that need it infrastructure is available.
Most application servers allow hot deployment nowadays, and equally most application servers are embeddable and allow them to be stripped down to remove features you do not need.
If it mainly for development, you should look a JRebel which provides this functionality transparently. I've heard they are working on a runtime solution, but I do not know if it is ready for primetime yet.
If you are really motivated to get this to work, then consider using OSGi. It has a steep learning curve, but once you grok it, it does most things right and works very well. I found the pax tools a good starting point but the eclipse toolchain also has good support for it.

Baffling Failure to Call External Executable From Within Java Program

All right, I've hit a bug that has simply confused the bejeebus out of me. I'm looking for ideas about what it could be that I can investigate, because right now, I got nothing. It goes something like this:
I have a standalone Java application that occasionally needs to twiddle the Line-In volume of the computer it's running on (a WinXP machine). It does this by calling a pair of external executables (written in VB6*) that can get and set various component volumes. (They can handle Line-In, Mic, Wave, CD, and the master volume control.)
There are several hundred units in the field, running on hardware (Dell machines) that my company provided and controls. At least several dozen clients are using this feature, and it works perfectly -- except for one instance.
For this one troublemaking machine, it simply doesn't work. I watch the volume sliders when the app is running, and when the volume is supposed to drop, they stay put. When I check the app's log file, it throws no errors, and appears to be executing the code that drops the volume. When I run the executables from the command line, they work perfectly.
I can't vouch for this machine being 100% identical to all the ones that are behaving properly, but we've been buying the same line of Dells for quite some time now; at a bare minimum, it's very, very similar.
So, turning my confusion into a bullet list:
If I'm doing something stupid in the Java code (i.e., not clearing my STDOUT/STDERR buffers), why is it only an issue on this machine?
If there's something broken in the VB6 executables, why do they work on every other machine and on this machine from the command line?
If there's some sort of hardware oddity on this machine, what sort of oddity could cause the volume control executables to fail only when called from within a Java application?
I am very confused. I do not like being confused. Anybody have any suggestions that may lead to my enlightenment?**
-* -- I know, I know, VB6, 1998 called and they want their obsolescent proprietary bug generator back, etc. Wasn't my decision. But the code works. Usually.
-** -- Insert Buddhism joke here.
Update Edit: Customer service may have stumbled onto something; it may be something to do with client configuration settings in the database. New evidence suggests that either something's misconfigured for that client or my software is doing something stupid in response to a specific configuration. And the problem may be more widespread than we thought, due to this particular feature not being as commonly used as I thought.
Responding to the comments:
Debugger: Theoretically possible, but looks like a massive headache given our setup.
High Verbosity Logging, Java: Good idea this, particularly given than the problem may be more widespread than I originally believed. Time to start revisiting some assumptions. And possibly clubbing them. Like baby seals.
High Verbosity Logging, VB6: A possibility; will need to be rolled-into the high-verbosity Java logging to trap the output, since my VB6-fu is so pitiably weak I don't know how to output text to a file. But, yeah, knowing whether or not the script is even getting called would be valuable.
Window Event Viewer: Not familiar with this tool. May have to correct that.
PATH problem: Doesn't feel likely; the Java code constructs a relative path to the executable that doesn't look like it's relying on any environment variables.
My thanks for the suggestions people have provided; at the very least, you've gotten my brain moving in directions that feel promising.
Solution Edit: And the winner is ... That's Not A Bug, That's A Feature! A feature gone horribly, horribly wrong. A feature that will now be neutered so as to stop bothering us.
A batch of invalid assumptions kept me from seeing it sooner, not the least of which was "I don't need to tool the code with more debug statements -- the statements already in there are telling me all I need to know!" DaDaDom, if you'd like to turn your comment into an answer, there's a shiny checkmark in it for you.
Thanks to everybody who chimed in with a suggestion. Now if you'll excuse me, my head is late for a meeting with my desk.
Here goes an answer:
Can you create a version of the software with verbose logging or could you even debug the code? At least then you can tell if it's in the java or the VB part.
Hmmmm. I've been told that executing programs from Java is either easy or hard. The easy part is starting them up. The hard part is dealing with the I/O streams (see my earlier question on using Runtime.exec()). Maybe the VB program is doing or expecting something weird on these particular machines that the Java code isn't working with properly.
edit: I also found a link to Jakarta Commons Exec:
Rationale
Executing external processes from Java is a well-known problem area. It is inheriently platform dependent and requires the developer to know and test for platform specific behaviors, for example using cmd.exe on Windows or limited buffer sizes causing deadlocks. The JRE support for this is very limited, albeit better with the new Java SE 1.5 ProcessBuilder class.
Reliably executing external processes can also require knowledge of the environment variables before or after the command is executed. In J2SE 1.1-1.4 there is not support for this, since the method, System.getenv(), for retriving environment variables is deprecated.
There are currently several different libraries that for their own purposes have implemented frameworks around Runtime.exec() to handle the various issues outlined above. The proposed project should aim at coordinating and learning from these initatives to create and maintain a simple, reusable and well-tested package. Since some of the more problematic platforms are not readily available, it is my hope that the broad Apache community can be a great help.
Have you considered the possibility that the authenticated user may not have permission to edit volume settings on the workstation? Does the program run correctly if you run as an 'Administrator'?

Categories

Resources