If a programmer developed a java application(say swing application) with out any log files(poor coding standards..).At one point of time,the application crashes.
Then how will one track the cause for the crash ?
Note: faced this scenario question in an Interview.
I replied like may be he possibly can track from JVM.(not sure...).
Please anyone tell me, how to track the issue?
If there has been an exception, generally you can examine the stack trace in the Standard Output (Standard Error), if you are in an IDE in the Console, that is the default target for jvm log. However in the case of "poor coding standards" as you say, the exception could be catched without printing the stack trace nor re-throwing it to upper levels...
Besides looking on the console for the stack trace, another option would be to reproduce it in the development environment and then add logging information or debug it.
Related
Actually, I receive a message through RabbitMQ which is large.
While consuming this message, we log it.
logger.info("payload: {}", payload);
I see the following exception in logs at the logger statement line.
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:421)
at java.lang.StringBuffer.append(StringBuffer.java:272)
at org.apache.log4j.helpers.PatternParser$LiteralPatternConverter.format(PatternParser.java:419)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:506)
at org.graylog2.GelfMessageFactory.makeMessage(GelfMessageFactory.java:37)
at org.graylog2.log.GelfAppender.append(GelfAppender.java:220)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
at org.apache.log4j.Category.callAppenders(Category.java:206)
at org.apache.log4j.Category.forcedLog(Category.java:391)
at org.apache.log4j.Category.log(Category.java:856)
at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:324)
After getting rid of the logger statement, the message was processed successfully.
So, can I be sure that the logger was causing the OutOfMemoryError?
Or it is something else that is causing the OutOfMemoryError?
Heap size is : 2048M
Q: So, can I be sure that the logger was causing the OutOfMemory error? Or it is something else that is causing the OutOfMemory Error?
A:
Based on the stack trace, yes.
From the trace you can evidently see that your log4j module (which is the logger object) was trying to perform a copyOf() operation but before the copy was done the program died with OutOfMemoryException.
As to how you would generally read the stack trace, this stackoverflow post can be a great help.
How to read and understand the java stack trace?
Quote:
Generally the exact reason for the Exception is at the first line of
your Stack Trace, and for more information about the cause of that
exception, you need to gradually move down, and the root cause can
often be found somewhere near the bottom of the stack trace.
I generally read the first line of the stack trace to determine what is happening, for your cause would be the OOM error, then I move to the last line and read from bottom up to see which object or area of code that could have caused the fault.
In your startup script of the application, memory parameters for initial heap size allocated to your application, and the maximum heap size for the same
Please refer this for details.
A startup command for the purpose can begin with something like
java -Xmx12288m <(followed by other necessary parameters)>
A sample command is given below for your reference
java -Xms1024m -Xmx12288m -XX:MaxPermSize=256m -Dlaser.home=$LASER_HOME -Djob=$job -Djava.library.path=$HADOOP_NATIVE -classpath "$CLASSPATH" $job_runner insights-workflow.xml $job run.date=$runDate env.type=$env
I faced a similar issue for my application, but it was related to spring. In my code, somehow an autowired dependency class got marked as abstract and I started getting this issue on server startup.
After almost a day of research we were able to identify the issue and fix it.
I have to develop new features and change some extisting ones in a buggy extensive Android application (where any changes may affect completely "unrelated" part of code) and I encountered a bug where application freezes (not responding).
So I figured it is probably a deadlock. But how to debug this? I cannot go step by step since we have many threads running and I dont know where to put a breakpoint...
Is there any way to break in debug and get a line (or part of code) where application is currently running?
Hope its not too chaotic, but I am exhausted from hours of testing...
If you are using eclipse.
You can suspend the debug session from the debug view.
Check the threads currently in action
From the stack trace of threads you can get a fair enough view of the current situation.
For further investigation you can use JConsole to debug the deadlock.
Check here https://kellicker.wordpress.com/2010/05/03/deadlock-debugging-in-eclipse/
cheers,
Saurav
As your app is multi-threaded, the best option may be to make use of debug logs in your code. You may get some clue about the part that is causing deadlock.
We have a Java SE application that occasionally hangs, without any reason.
At the moment, as I understand is best practice, I catch, log and display a message for Exceptions but not Errors. Obviously, when the application hangs (and never returns) there is no way for me to find out what went wrong - and crucially, no error message displayed.
Does this sound like an Error is being thrown? I've turned on logging with log4j, but I'm unsure whether this will even give any detail if such an error is thrown
Any help greatly appreciated!
I don't know why I never found myself having to use a debugger to step through my program and see what was going on, probably because I'm used to using interpreted languages such as PHP where it becomes very easy to add debugging code (print_r) and see changes live.
However with this new Java project I feel like I must learn the correct ways of debugging.
So this program, that I didn't write, runs on Tomcat and uses basic JSPs. The issue is that when I try to access a specific JSP page it throws an exception and gives me the stacktrace of what happened:
org.apache.jasper.JasperException: java.lang.NullPointerException
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:503)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:363)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:306)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.sgrp.singer.filters.SingerLoginFilter.doFilter(SingerLoginFilter.java:128)
How would I step through my program using a tool such as JDB? I can't really step through a specific class because I need to mimic what my JSP is doing... I would like to do this through the command-line, without using an IDE.
First, java has to be started with certain parameters to plugin a debugger:
-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
are the parameters used for our purpose. Afterwards, you use your IDE and connect the debugger remotely. You set a breakpoint to a piece of code (please make sure that the local files and the remote program are exactly the same revision) and generate the error. You can set breakpoints to uncaught exceptions as well.
As a hint: You can alter your referenced error-catching-JSP (error.jsp for us) to display not only the stacktrace of the caught exception (ex.getStracktrace), but also the causing stacktrace (ex.getCause().getStacktrace()). This might help identify higher level exception causes.
Edit: I'm sorry, without an IDE this is an information overflow that might not be possible for a human to do. Tomcat applications are complex on an architectural level, switching between a number of different classes for the easiest requests.
An alternative solution that may be easier to use than hooking a debugger to Tomcat:
First, take a look at the call stack. At the bottom, you'll see your class named org.sgrp.singer.filters.SingerLoginFilter. The problem lies here, at line 128 of method doFilter.
The first line says org.apache.jasper.JasperException: java.lang.NullPointerException. That means you've used an object whose value is null at line 128 of mentioned class.
Check out that code to find out what could be wrong. Also, add some print/logging statements to your code.
Debugging should be your last resort. You can gather a lot of information just by looking at your stack trace.
JDB could be used, it wouldn't be my first choice though.
Here is a good explanation how to use it:
http://www.javaworld.com/javaworld/javaqa/2000-06/04-qa-0623-jdb.html
You need to remember to include debug information when you compile your files and set up the Tomcat so you are able to connect to it, this is the string, as mentioned by other post:
-Xdebug -Xnoagent -Djava.compiler=NONE-Xrunjdwp:server=y, transport=dt_socket,address=8000,suspend=y
8000 can be replaced by any other numerical value. It basicaly tells jvm to listen on that port for a debugger.
What will happen now, is tomcat will start but suspend itself and wait for a debugger to attach before proceeding.
Start JDB and attach:
jdb -attach localhost:8000
in here, localhost can be replaced by where tomcat is running if it's running on a different machine and 8000 can be replaced with whatever port you set jvm in tomcat.
Now you can debug, you can see the debug instructions if you type help in jdb.
I have always used eclipse debugger, either running tomcat within eclipse or connecting eclipse to a separate, but local to eclipse, jboss server.
Works like a dream, no need to change jvm settings or anything.
Encountered a frustrating problem in our application today which came down to an ArrayIndexOutOfBounds exception being thrown. The exception's type was just about all that was logged which is fairly useless (but, oh dear legacy app, we still love you, mostly). I've redeployed the application with a change which logs the stack trace on exception handling (and immediately found the root cause of the problem) and wondered why no one else did this before. Do you generally log the stack trace and is there any reason you wouldn't do this?
Bonus points if you can explain (why, not how) the rationale behind having to jump hoops in java to get a string representation of a stack trace!
Some logs might contain sensitive data, log facilities are not necessarily secure enough to track that data in production.
Logging to much can result in too much information, i.e. no information at all for the sysadmins. If their logs are filled up with debug messages, they won't be able to recognize suspicious patterns. (Years ago I saw a system logging all system calls for security reasons. There were so many logs, that nobody saw it when some unprivileged users started to become root.)
Best thing to do to log everything with appropriate log levels, and be able to set log levels in production (at least in Java not that a big issue).
Please see these questions also
Logging in Java and in general: Best Practices?
Best practices for Java logging from multiple threads?
Important things here to consider
Handling Sensitive data
Compact exception messages and mailing those to appropriate fixers
Logging what is required. Because its logging expensive in terms space
and time
I generally do log the stack trace, because it has information for troubleshooting/debugging the problem. It's the best think next to a minidump and often leads to a solution simply by code inspection and identifying the problem.
BTW, I agree with sibidiba about the potential information disclosure about your app internals a full stack exposes: the function names, along with the stack call sequence, can tell a lot to an educated reader. This is the reason why some products only log the symbol address on the stack, and rely on the devs to resolve the address to the name from internal pdbs.
But in I reckon that logging text into files containing 1 line of error and 14 lines of stack makes it very difficult to navigate the error logs. It also causes problem on high concurency apps because the lock on the log file is held longer (or worse, the log files get interleaved). Having encountered these problems my self many times, along with other issues in supporting and troubleshooting deployments of my own apps, led me to actually create a service for logging errors at bugcollect.com. When designing the error collection policies I chose to collect the stack dumps every time, and to use the stacks as part of the bucket keys (to group errors that happen on the same stack into same bucket).
Restrictions on logging are often pushed through when developers log too liberally and sysadmins discover that the app, once put under a production load, thrashes and fills the HD with huge log files. It can then be hard to convince them that you've seen the error of your ways and have reduced logging (or adjusted log levels) sufficiently but really need those remaining log entries.
For us it is very simple: If there is an unexpected exception thrown, we log the stack trace along with as telling a message as possible.
My guess is that the developer who wrote the original code in the question, simply wasn't experienced enough to know that it is not enough with just the message. I thought so too, once.
The reason why it is convoluted to get a stack trace as a string is because there is no StringPrintWriter in the JRE - I believe the line of thinking has been that they provide a lot of orthogonal building blocks which you then combine as needed. You have to assemble the needed PrintWriter yourself.
Bonus points if you can explain (why,
not how) the rationale behind having
to jump hoops in java to get a string
representation of a stack trace!
Shouldn't you just log the throwable instead of going through hoops to print the stacktrace? Like this: log.error("Failed to deploy!", ex). Given a throwable, Log4J will print both the error message obtained via getMessage() and the stack trace.
What I've seen a lot is code logging an exception like this:
LOG.error(ex);
Because log4j accepts an Object as the first argument, it will log the String representation of the Exception, which is often only the name of the class. This is usually just an oversight on the developer's part. It's better to log and error like this:
LOG.error("foo happened", ex);
..so that if configured properly, the logging framework will log the stack trace.