Bug 536527 - Inspecting local variables fails when Debug Info is not available
Summary: Inspecting local variables fails when Debug Info is not available
Status: NEW
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Debug (show other bugs)
Version: 3.8.2   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: JDT-Debug-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2018-06-30 03:55 EDT by Gayan Perera CLA
Modified: 2022-09-14 09:12 EDT (History)
4 users (show)

See Also:


Attachments
Screenshot showing that it works with a JDK (89.97 KB, image/png)
2018-06-30 05:17 EDT, Holger Voormann CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Gayan Perera CLA 2018-06-30 03:55:01 EDT
import java.util.ArrayList;
import java.util.List;

public class HelloWorld {
	public static void main(String[] args) {
		ArrayList<String> names = new ArrayList<>();
		addToList(names, "Name1");
		addToList(names, "Name2");

		names.forEach(System.out::println);
	}

	private static void addToList(List<String> list, String value) {
		list.add(value);
	}
}

Debugging the following class at `list.add(value);` and stepping into the AbstractList add method, when i try to evaluate the argument passed into add method it fails saying "e cannot be resolved to a variable". This will be same in `addToList` method if i didn't build this class with debug info.

According to https://bugs.eclipse.org/bugs/show_bug.cgi?id=15489 seems that JDT is purely working on top of JDI. But this issue is 16 years old. The industry has evolved. IDE like intelliJ out of the box support this kind of debugging scenarios when there is not debugging info available.

Now in this specific example of debugging AbstractList i don't have any control over compiling it with debug info. So i think as a productive IDE it seems to support the developers to debug libraries like this.
 
I think if this is added to eclipse it will be really productive in this kind of scenarios where developers need to debug 3rd party libraries where debug info was not enabled.
Comment 1 Gayan Perera CLA 2018-06-30 03:57:26 EDT
Because of this bug i had to recompile the JDK source code with debug info to trouble shoot a production issue. I guess that is not acceptable for a developers to recompile a SDK just to debug few classes.
Comment 2 Holger Voormann CLA 2018-06-30 05:17:53 EDT
Created attachment 274713 [details]
Screenshot showing that it works with a JDK

Gayan,

It looks like you are using a JRE instead of a JDK to run your application (only a JDK contains line information and source code). Make sure in the launch configuration ("Run > Debug Configurations...", tab "JRE") a JDK is used as runtime JRE. If no JDK is available here, add a JDK in "Window > Preferences: Java > Installed JREs".

If my guess is correct, please close this bug as INVALID. Otherwise, please tell which JRE you are using in your debug configuration and what is different from what you see on the screenshot.
Comment 3 Gayan Perera CLA 2018-06-30 05:27:32 EDT
Yes might be correct on this specific example. But i do run with the JDK.

But what about the internal classes in JDK which are under packages like com.sun.*. I don't think all the classes in the JDK has debug info enabled. And what about 3rd party libraries. I don't think people only debug the classes in JDK which has debug info enabled all the time in all scenarios :(.
Comment 4 Holger Voormann CLA 2018-06-30 06:43:59 EDT
(In reply to Gayan Perera from comment #3)
> Yes might be correct on this specific example. But i do run with the JDK.
> 
> But what about the internal classes in JDK which are under packages like
> com.sun.*. I don't think all the classes in the JDK has debug info enabled.
> And what about 3rd party libraries. I don't think people only debug the
> classes in JDK which has debug info enabled all the time in all scenarios :(.

As the screenshot you shared on Twitter shows (https://twitter.com/gaparv/status/1012991689449803776), you are actually using a JRE ("/opt/java/jdk1.8.0_112/jre") shipped with Oracle's Java 8 JDK, not the JDK itself ("/opt/java/jdk1.8.0_112" without "/jre"). In your case, for "JRE home" you have to choose "/opt/java/jdk1.8.0_112" (instead of "opt/java/1.8" which seems to link to "/opt/java/jdk1.8.0_112/jre").

*.class files without debug information do not contain line numbers, parameter or variable names. Of course, you can decompile such *.class files, but then it depends on the used decompiler which name e. g. the parameter "e" gets in your example. Libraries without debug information are not intended to be debugged. From my point of view, an IDE should not show information that doesn't really exist. Anyway, that is not the subject of this bug report.
Comment 5 Gayan Perera CLA 2018-06-30 11:04:02 EDT
Well isn't there a JRE inside the JDK, because JDK is JRE + SDK right ? Well this is the output from ls -al from /opt/java directory

lrwxrwxrwx  1 gayanper gayanper   22 Apr 14 09:42 1.8 -> /opt/java/jdk1.8.0_112

As you can see the 1.8 dir link is linked to /opt/java/jdk1.8.0_112. If the /opt/java/jdk1.8.0_112/jre is not part of the JDK, where is the rt.jar for the JDK ?

By the way when i point /opt/java/jdk1.8.0_112 to eclipse this is how it picks up the JDK. I don't see another way it picks up the JDK in eclipse. And its same in other IDEs as well such as IntelliJ
Comment 6 Holger Voormann CLA 2018-06-30 11:16:00 EDT
(In reply to Gayan Perera from comment #5)
> Well isn't there a JRE inside the JDK, because JDK is JRE + SDK right ? Well
> this is the output from ls -al from /opt/java directory
> 
> lrwxrwxrwx  1 gayanper gayanper   22 Apr 14 09:42 1.8 ->
> /opt/java/jdk1.8.0_112
> 
> As you can see the 1.8 dir link is linked to /opt/java/jdk1.8.0_112. If the
> /opt/java/jdk1.8.0_112/jre is not part of the JDK, where is the rt.jar for
> the JDK ?
> 
> By the way when i point /opt/java/jdk1.8.0_112 to eclipse this is how it
> picks up the JDK. I don't see another way it picks up the JDK in eclipse.
> And its same in other IDEs as well such as IntelliJ
>

Yeah, you're right about that (Oracle ships an additional JRE with a JDK but it is installed somewhere else, at least on Windows).

Either your JDK is broken or it wasn't recognized correctly by Eclipse. Maybe this was because you choose the link "opt/java/1.8" instead of the real folder "/opt/java/jdk1.8.0_112". Can you please try to remove the JRE and add "opt/java/1.8" as JRE again? Does that make it look like in the screenshot I attached?
Comment 7 Gayan Perera CLA 2018-06-30 11:58:14 EDT
I can confirm that the JDK is not broken, because every thing works fine with the JDK, when i say everything other IDEs and built tools such as ant, gradle and maven.

I think your are thinking of the JRE which comes with the installation like in windows installations where it suggest to install a public JRE, but here its not the case, this a pure JDK 1.8, i think the layout is different starting with JDK 9 with project Jigsaw. And yes with JDK 9 and JDK 10 it works.

But this issue is not about the JDK and debugging. This issue is about support for inspection and evaluation when there is no Debug Info for a class which can be either inside JDK or in 3rd party library. I think it clearly mentioned in the issue description even though the example is some what misleading.
Comment 8 Holger Voormann CLA 2018-06-30 15:18:14 EDT
(In reply to Gayan Perera from comment #7)
> ... This issue is about
> support for inspection and evaluation when there is no Debug Info for a
> class which can be either inside JDK or in 3rd party library. I think it
> clearly mentioned in the issue description even though the example is some
> what misleading.

With your given example and instructions I get exactly what can be seen on the attached screenshot. I don't know what's wrong with that. Can you please give an example of how to reproduce your issue? Describe both what you actually see and what you expect.
Comment 9 Gayan Perera CLA 2018-07-01 02:03:33 EDT
New Example:
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class HelloWorld extends javafx.application.Application {

	@Override
	public void start(Stage primaryStage) throws Exception {
		VBox root = new VBox(new Button("Testing"));
		
		Scene scene = new Scene(root);
		primaryStage.setScene(scene);
		primaryStage.show();
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

1. Create a class with the above code.

2. Open com.sun.javafx.event.EventQueue and add a break point at line number 37 which is inside the `com.sun.javafx.event.EventQueue.postEvent(Event)` method.

3. Now debug the HelloWorld javafx application.

4. Move the mouse over the button in the HelloWorld application window.

5. By now the debug point we added in step 2 must hit.

6. Inspect or Evaluate the `event` parameter.

Outcome:
Error message with "Unable to evaluate the selected expression:". If i look the at variable view i can see the event variable is there with the name "arg0" which means this class is missing debug information.

Expected:
I should see the value of `event` local variable. and the IDE should map the `arg0` to `event` and show the value. This is done in IntelliJ. If you need to see how IntelliJ do this please refer the class 

https://github.com/JetBrains/intellij-community/blob/master/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java


Hope the above example is sufficient to describe the need of this issue. And the JDK setup is correct and the current setup works for my previous example :).
Comment 10 Andrey Loskutov CLA 2018-07-01 04:11:12 EDT
OK, last comment was helpful.

What we miss is the local variable name resolution for the code compiled without debug information (but with line information), and IDEA seem to have a workaround for this.

Much simpler example I've seen following IDEA tickets (https://youtrack.jetbrains.com/issue/IDEA-119698 and https://youtrack.jetbrains.com/issue/IDEA-114593) is

public class Symbols {
    public static void main(String[] args) {
        System.out.printf("%s\n", "Hello world");
    }
}

Put a breakpoint in java.io.PrintStream.format(String, Object...) and try to inspect the value of "format" parameter in the "Debug Shell" view:
 
format
	Evaluation failed. Reason(s):
		format cannot be resolved to a variable

The "Variables" view shows "arg0" variable content however. The point is that "Debug Shell" does not know that "arg0" variable in the debugger is same as "format" variable in the source, because this information is missing in the compiled class bytecode.

So what we need is to fetch the source code of the method we stopped at (if the source is available), and try to "guess" the variable names matching to the debugger names. In most cases we should be able to get the map by looking at the bytecode line numbers and corresponding source lines / AST.

So basically traverse AST, traverse bytecode and create names <-> lines maps, and try to map this info to the debugger position/variables.

If someone has some time, feel free to provide a patch.
Comment 11 Gayan Perera CLA 2018-07-01 07:34:51 EDT
@Andrey Loskutov you got my problem. And thanks for bringing up a more simpler example that what i presented, your comment brought some light into this issue. I will see if i have time to study the JDT Debug code and try to figure out a patch for this. But if there is any other contribute who has knowledge in this area and who would like to contribute that will be really great :)
Comment 12 Andrii Briantsev CLA 2022-09-14 09:12:33 EDT
Hi! 

Any news here. There are 4 years elapsed and I still can't debug JavaFX SDK :(

Best,
Andrii