Double-spaced Java stacktrace in Matlab errors - java

In Matlab, when a Java exception is thrown by a Java method invoked from M-code, it is converted to a Matlab error or MException, and the Java stacktrace is included in the MException's message. On Windows, the stacktrace is displayed double spaced. Here's an example.
package test;
public class Bummer {
public static void a() { b(); }
public static void b() { c(); }
public static void c() { d(); }
public static void d() { throw new RuntimeException("bummer"); }
}
Which produces this.
>> test.Bummer.a()
??? Java exception occurred:
java.lang.RuntimeException: bummer
at test.Bummer.d(Bummer.java:8)
at test.Bummer.c(Bummer.java:7)
at test.Bummer.b(Bummer.java:6)
at test.Bummer.a(Bummer.java:5)
>> disp(find(lasterr == sprintf('\r')))
61 95 129 163 197
This hurts readability, especially when you have a twenty call deep stack.
I believe this is because the stacktrace part of the error message is being constructed with DOS mode CRLF (\r\n) line endings. Which makes sense on a Windows machine. But the Matlab command window is kind of Unix mode, and converts \r\n to two line feeds.
Our current workaround is to use try/catch guard code like this around most Java method calls.
try
somejavaobject.SomeMethod();
catch err
rethrowmsg(err, 'Some additional details');
end
Rethrowmsg() is a function we wrote that munges err to convert \r\n to \n, incorporates additional details in the message, and then calls RETHROW.
Adding the workaround is a bit tedious and prone to be left out. And if you're doing "dbstop if all error", it won't fix the display of the error at that point. In the end, this is a minor annoyance, but when you spend all day debugging Matlab code, it adds up. And I'm curious about the Java exception/MException integration mechanism.
Is there a way to configure Matlab to construct the stacktrace part of the error message text with \n line separators so it displays single-spaced in the command window?

When the MATLAB Runtime intercepts the java exception, it uses the system line endings when it wraps it in a MException. To get around it, you can throw the exception on a different thread, or send the stack trace directly to stderr, such as with printStackTrace():
public class Bummer {
public static void a() { b(); }
public static void b() { c(); }
public static void c() { d(); }
public static void d() { new RuntimeException("bummer").printStackTrace(); }
}
Of course, it is a very bad thing to get a java exception in MATLAB. If you're using exceptions for things that are not really exceptional, then you may want to consider wrapping with a MException your users will find useful.
If you're using the exceptions to debug your java code, I find the stack trace analyzing functions of most java IDE's are able to deal with the extra line breaks nicely.

Try setting:
java.lang.System.setProperty('line.separator', sprintf('\n'));

Does using the FORMAT command improve the display at all? This helps display variables in a more compact form:
format compact
It may help display error messages in a more compact form too.

Related

Why static block are executed later?

P.S :
This question has been edited a few times as my previous code doesn't demonstrate the problem. There are some answers which may not make perfect sense against the edited question
I have a public class named Son.java
package com.t;
public class Son extends Father {
static int i;
static {
System.out.println("son - static");
i = 19;
}
{
System.out.println("son - init-block");
}
public static void main(String[] args) {
//Son s = new Son();
int a[] = new int[2];
System.out.println(a[5]);
}
}
class Father {
static {
System.out.println("f - static");
}
{
System.out.println("f - init-block");
}
}
When I run the program for the 1st time:
Output is:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at com.t.Son.main(Son.java:19)
f - static
son - static
And later when I run this program (order of output is random)
Output is:
f - static
son - static
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at com.t.Son.main(Son.java:19)
I have read that static blocks are executed as the classes are initalised.
But why does the exception has come first here and then static block is executed?
I am using Eclipse too to run my program.
Can somebody explain?
The exception doesn't happen first, you are just seeing the printout of the exception first.
Had the exception happened first, you would never have seen the rest of the output.
The reason for this is that you have output to both System.err (from your exception) and System.out in your program. The order in which these are printed to the screen is not defined, so therefore you can get them in different order.
Stack traces of uncaught exceptions are printed in System.err, which is an unbuffered stream. You print text to System.out which is a buffered stream and it is unpredictable whether it he buffer gets flushed before or after the stack trace is printed.
If you change all your print statements to System.err then the order of the output will become the order of printing, and it will always be the same order.
#Keppil's answer has nailed it.
I just want to point out something ... erm ... interesting.
The OP says this:
I am using Eclipse to run my program.
The knee jerk response would be to say "that isn't relevant" ... but in this case, I think it >>is<< relevant. I suspect that non-determinism in stdout/stderr timing is being is amplified by the fact that the output is going to a Eclipse "console" panel.
When an application is run from the command line, output to stderr and stdout probably gets merged into out stream somewhere in the OS kernel. And if not, the console program probably uses a select syscall to handle input from two sources ... and gives one stream priority over the other, 'cos that is the easy way to code it. As a result, you would expect the output to appear on the console in a mostly consistent order, even though order is non-deterministic.
But when the application writes to an Eclipse console, Eclipse probably uses a separate thread to read each stream. Assuming that both threads are blocked in read syscalls, and input arrives at roughly the same time on both streams, it will be up to the thread scheduler to decide which thread gets woken first. That is going to be far less predictable that the behaviour of a select ... or of stream merging in the kernel.
Either way, my observation is that reordered stdout / stderr output is more prevalent with an Eclipse console than when you are using a "native" console.
As the asker said main belongs to Son class and is extending Father. I modified the code a little, so I was able to compile.
class Father {
static{
System.out.println("f - static");
}
}
public class Son extends Father {
static {
System.out.println("son - static");
}
public static void main(String[] args) throws ArrayIndexOutOfBoundsException{
int a[] = new int[2];
System.out.println(a[3]);
}
}
And the output is:-
f - static
son - static
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at kanwal.Son.main(Son.java:20)
Its working exactly, the way it is supposed to.
EDIT:-
This answer was made, before OP edited the question.

Supressing console (disp) output for compiled MATLAB > Java program (using MATLAB Compiler)

Edit 2 After recieving a response from Mathworks support I've answered the question myself. In brief, there is an options class MWComponentOptions that is passed to the exported class when instantiated. This can, among other things, specify unique print streams for error output and regular output (i.e. from disp()-liked functions). Thanks for all the responses none the less :)
====================================================================
Just a quick question - is there any way to prevent MATLAB code from outputting to the Java console with disp (and similar) functions once compiled? What is useful debugging information in MATLAB quickly becomes annoying extra text in the Java logs.
The compilation tool I'm using is MATLAB Compiler (which I think is not the same as MATLAB Builder JA, but I might be wrong). I can't find any good documentation on the mcc command so am not sure if there are any options for this.
Of course if this is impossible and a direct consequence of the compiler converting all MATLAB code to its Java equivalent then that's completely understandable.
Thanks in advance
Edit This will also be useful to handle error reporting on the Java side alone - currently all MATLAB errors are sent to the console regardless of whether they are caught or not.
The isdeployed function returns true if run in a deployed application (with e.g. MATLAB Compiler or Builder JA) and false when running in live MATLAB.
You can surround your disp statements with an if isdeployed block.
I heard back from a request to Mathworks support, and they provided the following solution:
When creating whatever class has been exported, you can specify an MWComponentOptions object. This is poorly documented in R2012b, but for what I wanted the following example would work:
MWComponentOptions options = new MWComponentOptions();
PrintStream o = new PrintStream(new File("MATLAB log.log"));
options.setPrintStream(o); // send all standard dips() output to a log file
// the following ignores all error output (this will be caught by Java exception handling anyway)
options.setErrorStream((java.io.PrintStream)null);
// instantiate and use the exported class
myClass obj = new myClass(options);
obj.myMatlabFunction();
// etc...
Update
In case anyone does want to suppress all output, casing null to java.io.PrintStream ended up causing a NullPointerException in deployment. A better way to suppress all output is use to create a dummy print stream, something like:
PrintStream dummy = new PrintStream(new OutputStream() {
public void close() {}
public void flush() {}
public void write(byte[] b) {}
public void write(byte[] b, int off, int len) {}
public void write(int b) {}
} );
Then use
options.setErrorStream(dummy);
Hope this helps :)
Another possible hack if you have a stand-alone application and don't want to bother with classes at all:
Use evalc and deploy your func name during compile:
function my_wrap()
evalc('my_orig_func(''input_var'')');
end
And compile like
mcc -m my_wrap my_orig_func <...>
Well, it is obviously yet another hack.

Java 7: throw exception without stack trace

EDIT2
#paradigmatic made a good point in suggesting to redirect rather than throw the exception; that solves the logging issue. The problem in Play 2 is that redirects need to occur within so-called Action scope, which is not always the case with date parser calls.
As a workaround, I went with Play's global interceptor, presumably the equivalent of a Java servlet filter.
val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)
override def onRouteRequest(r: RequestHeader): Option[Handler] = {
import play.api.i18n.Messages
ymdMatcher.findFirstIn(r.uri) map{ ymd=>
try { ymd2Date( ymd); super.onRouteRequest(r) }
catch { case e:Exception => // kick to "bad" action handler on invalid date
Some(controllers.Application.bad(Messages("bad.date.format")))
}
} getOrElse(super.onRouteRequest(r))
}
EDIT
Here 's a little context to work with:
// String "pimp": transforms ymdString.to_date call into JodaTime instance
class String2Date(ymd: String) {
def to_date = {
import play.api.i18n.Messages
try{ ymdFormat.parseDateTime(ymd) }
catch { case e:Exception => throw new NoTrace(Messages("bad.date.format")) }
}
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
}
#inline implicit final def string2Date(ymd: String) = new String2Date(ymd)
and a test custom exception handler:
public class NoTrace extends Exception {
static final long serialVersionUID = -3387516993124229948L;
#Override
public Throwable fillInStackTrace() {
return null;
}
public NoTrace(String message) {
super(message);
}
}
Calling the date parser on an invalid yyyyMMdd string logs 30 line stack trace to the log (this occurs upstream by Play framework/Netty container, better than default 100 line trace):
"20120099".to_date
ORIGINAL
Have an issue where my application.log is getting filled with errors related to a uri date parser operation that should succeed given a valid yyyyMMdd uri date.
However, some users try to circumvent this by entering invalid dates in hopes of gaining free access to paid subscriber-only content. It's pointless, as it simply won't work, but regardless, I have MBs of these error traces in my application log.
Is there a way to throw a truly trimmed down Exception to the log? I found this SO answer, but in my application it looks like the container (Play framework on Netty) gets into the mix and logs its own 30 line stack trace to the log (30 lines is better than 100, but still 29 too many)
Similarly, I found this thread in regard to Java 7 and the new option to suppress stack trace; however, for some reason, despite being on Java 1.7, with Eclipse configured for Java 1.7, only the old 2 param method of Throwable is available (and I do see the 4 param method when I click through to the Throwable class; maybe a Scala 2.9.2 library issue?)
At any rate, ideally I can simply log a 1-line exception message and not the kitchen sink.
Simply override this method in your custom exception class:
#Override
public Throwable fillInStackTrace() {
return this;
}
after adding this method your trace method will not print
Your trouble is that although you can suppress the stacktrace of the exception your own code threw, there is nothing you can do about the exception it will be wrapped into by the framework. The only avenue I can see is not allowing the framework to catch your exception at all (doing your own top-level handling) or tweaking the logging configuration.
I think you have two options:
Control the logging to not save stack traces for some exceptions.
Write a post-processor that filters out the traces from the log file.
Unless you are in danger of running out of disk space, I think #2 is the better option, because if you do have a bug you can go back to the full log and have all the exception history.
The philosophy behind idea #2 is that disk space is cheap, but information can be precious during debug. Log a lot of data. Normally, use scripts to examine the log after it has been written to disk.
For example, if there is a type of log entry that you never expect to see, but that demands immediate action if it does appear, write a script that searches for it, and send you an e-mail if it finds one.
One of the most useful forms of script in this approach is one that drops stack trace lines. Usually, you only need to know what exceptions are happening, and the stack trace takes up a lot of screen space without telling you much. If you do need to investigate an exception, go back to the full log, find the exception line, and look at the stack trace and at what was happening immediately before the exception.
If there are too many of your date exceptions, have the script drop even the exception line. If you want to track how often they are happening, run a script that counts date exceptions per hour.
That sort of script typically costs a few minutes of programming in your favorite regex-capable script language.

Control the execution of a java program from my java program

public class LineNum1 extends Thread{
public synchronized void run()
{
try {
Hello.main(null);
System.out.println("Stack Trace of thread"+ this.currentThread().getName());
System.out.println(this.currentThread().getStackTrace()[1].getLineNumber());
System.out.println("End of Stack Trace");
} catch (Exception e1) {
e1.printStackTrace();
}
}
public static void main(String[] args) {
LineNum1 t = new LineNum1();
t.start();
}
}
I'm developing a code coverage tool.
Using the above program I'm executing Hello.java from here. Is there any method where I can get the control over Hello.java?
Or to make my life simpler can i get the line numbers of the executed lines(Execution path) of Hello.java?
You want to use the Java Debug Interface. It's the Java library that is used for writing Java tools like debuggers. It'll allow you to step through the program, query for line numbers and whatnots as you go.
There's a simple demo application for it called trace that does most of what you want already: http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/trace.html
There's a lot of documentation for it, if you've got the time to read it:
http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/index.html
You can probably execute the second Java class as a Process and read the output yourself.
I have not completed the code coverage completely yet. But I have used bytecode instrumentation to instrument the methods, hence i get the log of all the methods I've visited. This Javassist Turtorial might help you.

Java entering an if statement that is false

I'm running into the strangest error in this program, which is confirmed when debugging it. I have the following code (boiled down to highlight the problem, of course):
BHFrame.java
public class BHFrame
{
private boolean uSS;
private StateSaver stateSaver;
public BHFrame(boolean useInternalStateSaver)
{
//Init code
uSS = useInternalStateSaver;
//More init code
System.out.println(uSS);
if (uSS)
{System.out.println("Entered 1");
stateSaver = new StateSaver(title, false);
stateSaver.addSaveable(getThis());
}
//More init code
System.out.println(uSS);
if (uSS)
{System.out.println("Entered 2");
try
{
stateSaver.loadState();
stateSaver.putState(getThis());
}
catch (IOException ex)
{
alertUserOfException(ex);
}
}
}
}
GUI.java
public class GUI extends BHFrame
{
public GUI(boolean useInternalStateSaver)
{
super(useInternalStateSaver);
}
}
Main.java
public class Main
{
public static void main(String[] args)
{
GUI gui = new GUI(false);
}
}
Output
false
false
Entered 2
Exception in thread "main" java.lang.NullPointerException
at bht.tools.comps.BHFrame.<init>(BHFrame.java:26)
at bhms.GUI.<init>(GUI.java:5)
at bhms.Main.main(Main.java:5)
The class BHFrame is extended and run from a child class that calls this constructor, but that really shouldn't affect this behavior. The problem is that, when false is passed to the constructor as useInternalStateSaver, the first if (uSS) is skipped, but the second is entered. Upon debugging, I found that uSS is false throughout runtime, including on the line of the second if statement, here. Why would Java enter an if statement when the condition returns false? Before you ask, I did delete the .class files and recompile it just in case there was some residual code messing with it, but I got the same result. And rest assured, all the references to the uSS variable are displayed here.
Solution
As it turns out, this appears to be a bug in NetBeans 7.1 Build 201109252201, wherein the IDE doesn't properly insert new code into the compiled .class files. The problem was fixed by compiling the files externally. A bug report has been submitted.
Whatever's throwing that exception is probably not in your posted code.
It's not being caught by your catch statement, which only catches IOException.
It's a NullPointerException and can occur anywhere.
You have shown no indication that the code inside your if block is actually executing. In your screenshot, there is absolutely know way of knowing if your if block is entered or not. There are no logging statements.
Add debugging messages at various points to see exactly what is happening. Or, you know, look at line 26 (wayyyyy before your posted code) to see why you're getting a NullPointerException.
I've seen crazy stuff like this when there is bad RAM on the machine. You might want to run memtest86.
You might also consider deleting all of your project class files, and then doing a build. Maybe you changed Main.java, but it was never recompiled. I hate that when that happens.
This is just a guess, because I can't see the code you are mentioning, but I reckon you have defined a local variable uSS in the second //More init code segment.
Once you define a local variable named the same as an instance variable, it 'hides' the instance variable. Better to qualify all instance variables with this.
So, try qualifying all above accesses of uSS with this. ... (this.uSS)
Even if this isn't the issue, it might be better to post the full code anyway.
HTH

Categories