Java

In an earlier posting, I showed how to log particular expressions like the current value of a method parameter to the console during a debug session, using JDeveloper, without the need to continously press the “resume” button. The same is also possible in Eclipse. Lets assume we have the following code which does some calculations:

package com.example;

public class DebugSample {
    
    private double calculate(double input) {
        return Math.sin(input * input); 
    }

    private void processValue(double value) {
        // ...
    }

    private void run() {
        double value = 0.0;
        while(value < 20) {
            double newValue = calculate(value);
            processValue(newValue); // do some processing with the calculated value
            value = value + 0.5;
        }
    }

    public static void main(String[] args) {
        new DebugSample().run();
    }
}

Now, if we want to check the contents of the calculated value (newValue) inside the while loop, we can simply set a breakpoint at the line after the call to the calculate() method: IMG Then, we can launch the application under debugger control and inspect the current contents of the newValue variable in the “Variables” tab: IMG By pressing Resume (or F8), we can watch how the value changes in each iteration of the for-loop. However, this can be tedious, especially if we expect that some issue only occurs after several dozens of iterations. We could add a System.err.println() statement to dump the values to the console, but in more complex environments this is often not possible (or at least not simple), e.g. when doing remote debugging of a web application. Fortunately, we can define a conditional breakpoint and use a side effect of the breakpoint condition to log variable contents to the console when the breakpoint is hit, while letting the application resume automatically. Simply select the breakpoint in the “Breakpoints” tab and check the “Conditional” flag: IMG By setting “Suspend when true” (which is the default), we can control through the return value of the condition whether the application should be suspended or resumed automatically. In the text field below, we define the condition (which is really Java code fragment) which gets executed every time the breakpoint is hit. In our case, the code finally returns “false”, which means that the application is never suspended when the breakpoint is hit, but resumes immediately. Since the condition is not only a closed expression, but a real Java code fragment including more than one statements, we could also add an if condition to restrict the output to specific value ranges: IMG In this example, the output only occurs when value is larger than 10.

Examining nested stack traces

I often read Java Stack traces bottom up when I examine them for the first time – simply because this is the code path which was executed when the exception occurred. However, it can happen that the last line of a stack trace shows something like ... 2 more – so, one might ask why can’t the runtime just dump those missing lines, along with all the other stack trace elements? Real life server stack traces sometimes contain dozens of lines, it should not matter to print those additional lines, right? And often those lines contain just the information you require to see from where the problematic code which caused the exception was called … The thing is: those lines are actually in the stack trace. Lets consider this example:

Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: Exception thrown
	at com.example.TraceTest.doSomething(TraceTest.java:13)
	at com.example.TraceTest.run(TraceTest.java:6)
	at com.example.TraceTest.main(TraceTest.java:22)
Caused by: java.lang.RuntimeException: Exception thrown
	at com.example.TraceTest.throwAnException(TraceTest.java:18)
	at com.example.TraceTest.doSomething(TraceTest.java:11)
	... 2 more

As you can see, the last line reads ... 2 more, but it might be crucial for the further analysis to know from where the doSomething() method was called. In order to get this information, we need to look further up in the stack trace: There, we again find the doSomething() method at the top and see that it was called from the run() method. In other words, the initial entry point for the code flow is the last element of the first stack trace block – from there, we can follow to the next stack trace block to see where the exception was finally thrown:

The reason for this is that the original exception was wrapped as nested exception into another exception. The following is the code which was used for the test above:

package com.example;

public class TraceTest {
    
    public void run() {
        doSomething();
    }

    private void doSomething() {
        try {
            throwAnException();
        }catch(RuntimeException re) {
            throw new RuntimeException(re);
        }
    }

    private void throwAnException() {
        throw new RuntimeException("Exception thrown");
    }

    public static void main(String[] args) {
        new TraceTest().run();
    }
}

Real stack traces might also contain more than one nested exception, so it might be necessary to follow them more than once.

In any case, the stack trace still contains the whole code path from the entry point (usually main) to the place where the exception was thrown.

See also how to print the full stacktrace in java on StackOverflow.

Eclipse Luna crashes with KDE on Ubuntu 14.04 LTS (Trusty)

This is an issue I came across today, after I upgraded my system to Ubuntu 14.04 LTS (Trusty) some days ago and after I also upgraded to Eclipse Luna 4.4.1 (using JDK 8u31): When importing an existing project into the workspace, the “Import Projects” dialog (where you can select the root directory) still opens, but then the JVM crashes with this assertion:

java: /build/buildd/gtk2-engines-oxygen-1.4.5/src/animations/oxygencomboboxdata.cpp:87: 
void Oxygen::ComboBoxData::setButton(GtkWidget*): Assertion `!_button._widget' failed.

After some searching, I found that this is a known KDE bug (there is also a corresponding Eclipse bug) and it has already been fixed in oxygen-gtk2-1.4.6. This version is already available in Ubuntu 15.04 (Vivid), but not yet in 14.04, so I crated a backport package – you can get it from my Personal Package Archive. After installing the upgraded package, the issue is gone (what remains is a message like Oxygen::WindowManager::wmButtonPress - warning: a button was already set for this combobox which is obvious when we look at the diff (have a look at the oxygencomboboxdata.cpp file). A different workaround in case you do not want or can install the new oxygen-gtk version is to set a different GTK style in the KDE control center:

Open the KDE System settings and select “Application Appearance”. In the dialog choose the GTK category and choose a different GTK style in the “Select a GTK2 Theme” dropdown, e.g. “Ambiance” as in the example below:

Some background on Generics: dumping a Map

In Java, dumping a Map to see what key/value mappings it contains is quite easy. Lets assume we have a factory method which returns a map, containing some String to Long mappings:

Map<String, Long> map = createMap();

The toString() method of the Collection classes usually provide a useful implementation, so that we can simply use

System.err.println(map);

to dump the map. If we want to have more control over the output format, e.g. one line per map entry, we can use a simple loop to iterate over the entries:

Set<Entry<String, Long>> entries = map.entrySet();
for (Entry<String, Long> entry : entries) {
    String key = entry.getKey();
    Long value = entry.getValue();
    System.err.printf("%s=%s\n", key, value);
}

When running this code with the map returned from the createMap() method, we get

Exception in thread "main" java.lang.ClassCastException: com.example.Key cannot be cast to java.lang.String
	at com.example.MapSample.run(MapSample.java:25)
	at com.example.MapSample.main(MapSample.java:54)

Ehm… wait a moment … why do we get this exception in the line which executes String key = entry.getKey();? We did not get any compile time errors or even warnings, and entry.getKey() is declared to return a String due to the definition of entry as Entry<String, Long>. Also, the Map is declared as Map<String, Long> – so each key element in the map must be a String, right? No. Lets examine how the map is created in the createMap() factory method:

private Map<String, Long> createMap() {
    Map result = new HashMap();
    result.put("one",  1L);
    result.put(new Key(), 3L);
    result.put("two",  2L);
    result.put("five",  5L);
    result.put("four",  4L);
    return result;
}

Obviously, we are allowed to use different types than String as a key, an instance of the Key class in this case. This is possible since Map and HashMap are used as raw types here, instead of parameterized types. The Java compiler will issue some warnings, but will still compile the method as such (and even the warnings can be switched off with an annotation like @SuppressWarnings({ "unchecked", "rawtypes" })). Remember that Generics (paremeterized types) are syntactic sugar only – internally, during runtime, everything is raw types, with the necessary casts automatically applied where necessary. These casts succeed when the parameterized types are used throughout the application. If this was properly done in the createMap() method, the compiler would not let us use Key as a key value. However, due to the usage of Map as raw type, we can. And then, during runtime, the casts mentioned before will fail horribly. In the example above, entry.getKey() still returns an Object reference, but due to the type parameters the compiler automatically casts the result to a String. You can verify this in the byte code which contains a corresponding checkcast instruction after entry.getKey() has been invoked. The general rule is: do not use raw types. Especially with large legacy code bases, there are sometimes occasions where Collections are still created without the proper usage of type parameters (but later returned through parameterized types). Thus, the learning is: Even if you get a reference to a properly parameterized Collection type, do not be surprised if there are other types stored in it when you iterate over the Collection values or keys. Back to our dumping method, we can simply solve the issue by not forcing any implicit casts:

Set<Entry<String, Long>> entries = map.entrySet();
for (Entry<String, Long> entry : entries) {
    Object key = entry.getKey();
    Object value = entry.getValue();
    System.err.printf("%s=%s\n", key, value);
}

When run, this will produce the expected output:

four=4
one=1
com.example.Key@15db9742=3
two=2
five=5