No single method in a program "knows" where it is on the stack. All it knows is its own little job, and it does that and returns. So when an Exception is thrown and a stack trace is printed, where does this come from?
Is there implicitly a separate Thread running alongside of every application in the JVM that's monitoring the state of the program? Or does the JVM itself hold this information and the Exceptions somehow pull that data from it when they are thrown?
If either of these is the case, is it possible to use some call to retrieve a stack trace (either from the monitor Thread or the JVM) without throwing an Exception?
Every thread will have its own stack. Each method call creates a stack frame. If something wrong happened in code of any method, that will propagated to caller method. This way JVM can trace which method generated error and what is the call hierarchy.
If you observe the stack trace properly, you will see the method where error occured at top and the hierarchy in bottom.
There is a great lecture in youtube by a Stanford professor to understand how does it work. I would suggest watching it.
NOTE: This is theory. If you would like to know how API works, #Peter Lawrey answer may help you.
It comes from the Thread class that is running through the code.
Thread.dumpStack();
To see it you can just:
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (int i=0; i < trace.length; i++)
System.out.println("\tat " + trace[i]);
You can know the Thread a method belongs to by using Thread.currentThread. Using this thread, you can get the StackTrace, because there is a stack for every thread in the JVM. Also, the main program runs in the main thread.
When you create a Throwable (not when you throw it) it records the stack trace is a low level/hidden way associated with the Throwable. When you call getStackTrace() the first time it creates the StackTraceElement[] objects from the low level information. It doesn't this lazily as the stack trace is often not used.
Related
How do we get the stacktrace for a successfully executed line in Java? It's needed to debug an issue.
I dont want a normal stacktrace, I want to know what a particular line is doing behind the scenes.
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("/opt/data/ws_server.xml"));
serviceHelper = (ServiceHelper)factory.getBean("serviceHelper");
//Assuming no exceptions, print/view stack trace of above line (factory.getBean).
I want to see the stacktrace for factory.getBean - like below, to understand what factory.getBean is doing.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:757)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:721)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:384)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
- locked <0xffffffff58100608> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
In the end, you are asking for some sort of instrumentation. In other words: you want to tell the jvm to keep track of the call stack and more importantly, make that information available to you programmatically.
And even when you only want that to happen for specific methods, the jvm still has to track all method invocations, as it can't know whether one of the methods to track is called in the end. Thus there is no way of tracking method invocations easily without performance impacts. And the tools I know that can keep that performance impact on a reasonable level, like XRebel are for later evaluation, not for programmatic consumption.
In other words: the only solutions to hang situations are:
doing a thread dump and analyzing it
doing extensive logging/tracing while your code is running, to analyze that in case or hangs
Just to be clear: what you are asking for, to get a stack trace of already executed code after the fact is impossible to achieve!
Please look in following answer.
Get current stack trace in Java
Basically it is Thread.currentThread().getStackTrace()
I occasionally come across java.lang.Error (just Error, not one of its subclasses) being thrown, with no apparent source and no detail message. Example:
java.lang.Error
at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:211)
at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:190)
(rest of stack trace omitted)
This is LoadController.java:211:
FMLLog.log(modId, Level.TRACE, "Sending event %s to mod %s", stateEvent.getEventType(), modId);
Another example:
java.lang.Error
at java.util.ArrayList.indexOf(ArrayList.java:317)
at java.util.ArrayList.contains(ArrayList.java:300)
(rest of stack trace omitted)
This is ArrayList.java:317:
if (o.equals(elementData[i]))
(Links go to full stack traces and sources.) All circumstances I can think of that result in an Error actually result in a more specific subclass of it, and/or a message with details. What could cause just an Error to be thrown in these places?
I figured this out myself. Minecraft has a server watchdog thread (net/minecraft/server/dedicated/ServerHangWatchdog.java in the MCP source), which monitors the main server thread and causes this to happen if it takes too long to run a single tick. The code that looked like it was throwing the Error in this stack trace was in fact completely unrelated to it.
What does this method do? I found an Android code on internet about exception handling in which the guy used this function in catch{} He didn't explain properly why this function/method is used.
Check this JavaDoc. Stacktrace is used in debug mode. Each method is displayed from most generat to the specific method where the exception was thrown.
Think about it as a stack which has each method call involved in the cause of that exception.
In addition, using printStackTrace() method is considered bad practice because System.err file is used and the method is not thread safe. Better use a logger.
it prints the stack where the exception occured. If there is debug information then it will show the line of code where each call was at to help you find the source of the problem.
This method prints the entire stack trace of the methods that got called before the exception has been raised. It is very helpful while debugging since you will know the path of execution.
It prints the stack trace of the Exception to System.err.
It's a very simple, but very useful tool for diagnosing an Exception. It tells you what happened and where in the code this happened.
source: What is the use of printStackTrace() method in Java?
I am getting java.util.ConcurrentModificationException but I need to figure out which class gives me this exception. The code has numerous classes and packages and it is difficult to figure out where the error comes. The exception shows the problem of ArrayList. It doesn't catch exeption when I use exception handling in suspected areas.
Any way out?
If you're using a modern IDE, eclipse for example, then you can run the application in debug mode and set a breakpoint on any Exception. With the effect: the application will stop each time the exception is thrown (in the entire JVM) and you get a stack trace.
That makes it quite easy to identify the caller (and the actual thread, if it is a concurrency issue)
playn.java.JavaGroupLayer.paint(JavaGroupLayer.java:96)
That's the bad guy. It's the paint method your JavaGroupLayer class. It probably has a for loop that iterates through an array list and at one point it detects, that the list has been modified.
Do you use threads in your swing application? In that case, double check that they do not modify the layout.
Usually start at the top of stack trace, and the first class that you wrote/recognize as yours should be your entry point. Afterwards, you probably make calls in other classes/methods, so you can follow the stacktrace and hence the offending code.
Additionally : What you are probably doing (I have done that in the past myself) is trying to modify a collection, while iterating over it. This is what concurrent modification means. Try to see where you are doing that and should be it.
Go through the stack trace from the top to bottom and the first class that belongs to your source code is the one that has received the exception from an ArrayList trying to do something illegal with it. Then check which threads are accessing that instance of an ArrayList in the same time and protect it with synchronized methods or synchronized blocks.
A common mistake is to discard the exception, only read the message or toString the exception. If you print the stack trace, you will be able to see exactly where (the class, the method and the line) of each level of the stack.
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at playn.java.JavaGroupLayer.paint(JavaGroupLayer.java:96)
at playn.java.JavaPlatform$1.paint(JavaPlatform.java:222)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5138)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1454)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1385)
In your IDE, you should be able to click on each line to see the code involved.
Given this is in a package, it is more likely that the problem is that you have used the library incorrectly. It appears that plyn is not mult-thread safe and you have a attempted to change a data structure in another thread instead of using the swap AWT thread.
Identify the list, then either change the iteration to use list iteration (for i=0; i < list.size(); i++) rather than Iterator iteration (for x:list)
Or you can make a shallow copy of the list and iterate that.
I'm working with threads but after a time, most of them stop doing their job. The first thing I thought was a deadlock, but all are with state RUNNING.
I suppose there is an error in my logic or a new characteristic that I not realized and I must handle (it's a webcrawler).
Is it possible to get the current executing method or operation? I want this to see where my threads are trapped.
EDIT: I think that is something I need to handle or there is error in my logic because this happens after a time executing, not imeddiatly after the start.
A debugger is the way to go. This is what they are designed for.
Java debuggers with threading support are built into both the Eclipse and Netbeans IDEs.
Make VM to dump the threads (Ctrl-Break). Find your threads in the list. Look at the topmost stacktrace method. Done.
You can get the current stack trace in Java. You will get an array of StackTraceElement elements.
The first item in the array is the currently executing method.
See the following question for how to get the stack trace:
Get current stack trace in Java
Code might look like:
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
StackTraceElement yourMethod = trace[1];
System.out.println(yourMethod.getMethodName());
You have 2 options:
Use debug to get some understanding that was executed and what not.
Use a lot of logmessages (you can also produce stacktraces in that messages)
Thread dumps are the right solution for the problem. If you want to do it programmatically within the process (some kind of monitoring logic), then java.lang.management.ThreadMXBean provides access to all threads along with their current stacks at the time.
It is, throw an exception, catch it immediately and save the stack. This is about as performant as asking an elephant to fly overseas but it's possible since it sort of extracts the current call stack to something you can work with.
However, are you sure you haven't run into a livelock?
Do you suppose your web crawler program is in a loop processing the same urls. Add some high level logging so each thread writes what it's processing.