eclipse-jdt / eclipse.jdt.core

Eclipse Public License 2.0
164 stars 130 forks source link

Reproducer for "j.l.O cannot be resolved. It is indirectly referenced from required .class files" #3045

Closed srikanth-sankaran closed 1 month ago

srikanth-sankaran commented 1 month ago

Today, while experimenting with something altogether different I ran into this notorious and slippery problem that has been plaguing us for a while. I hope this is a legitimate reproducer that offers some insight into this problem.

(0) Download and keep the following files:

ecj-3.8.jar and ecjsrc-3.8.jar

(1) Launch a recent eclipse version IDE on a blank workspace.

I happen to use:

Eclipse SDK

Version: 2024-12 (4.34) Build id: I20240923-1800

  1. Create a project by pasting the following code on to the package explorer:
import org.eclipse.jdt.internal.compiler.batch.Main;
public class X {
    public static void main(String[] args) {
        Main.main(args);
    }
}

(3) For the project's JRE use jdk-20

(4) Add the 3.8 ecj files to the project and configure project build path so ecj-3.8.jar is added to the class path and ecjsrc-3.8.jar is configured as the source attachment to ecj-3.8.jar

(5) Create a run configuration for a Java application with X as the main class and as arguments pass X.java with X.java's contents set to:

public class X {}

(6) Run and you will get:

----------
1. ERROR in C:\tmp\X.java (at line 1)
    public class X {}
    ^
The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files
----------
2. ERROR in C:\tmp\X.java (at line 1)
    public class X {}
                 ^
Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
----------
2 problems (2 errors)
srikanth-sankaran commented 1 month ago

While I have documented specific versions I used to observe the problem (consistently reproducible) it is likely the problem may not need those exact versions to be observed. For example, it is not clear jdk-20 must be the project JRE for the problem to manifest. Etc.

srikanth-sankaran commented 1 month ago

@stephan-herrmann and @jarthana - let us discuss. I hope this is a legitimate reproducer that sheds light into this vexing problem and helps us solve at least some slices of it.

Let me know if for some reason you don't observe the problem or if you think this is not a legitimate reproducer for some reason

(@jarthana already confirmed that he is able to observe the problem)

srikanth-sankaran commented 1 month ago

Error reported here:

ProblemReporter(ProblemHandler).handle(int, String[], int, String[], int, int, int, ReferenceContext, CompilationResult) line: 117  
ProblemReporter(ProblemHandler).handle(int, String[], String[], int, int, ReferenceContext, CompilationResult) line: 201    
ProblemReporter.handle(int, String[], String[], int, int) line: 2132    
ProblemReporter.isClassPathCorrect(char[][], CompilationUnitDeclaration, Object) line: 4162 
CompilationUnitScope.getDefaultImports() line: 560  
CompilationUnitScope.checkAndSetImports() line: 162 
LookupEnvironment.completeTypeBindings() line: 209  
Compiler.internalBeginToCompile(ICompilationUnit[], int) line: 746  
Compiler.beginToCompile(ICompilationUnit[]) line: 383   
Compiler.compile(ICompilationUnit[]) line: 428  
Main.performCompilation() line: 3891    
Main.compile(String[]) line: 1684   
Main.main(String[]) line: 1397  
X.main(String[]) line: 4    
srikanth-sankaran commented 1 month ago

this.environment.getTopLevelPackage(TypeConstants.JAVA); returns null in org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.getDefaultImports()

srikanth-sankaran commented 1 month ago

Unfortunately I need to close shop to head out on a road trip ... Will look into this if I can squeeze some time over the next days

srikanth-sankaran commented 1 month ago

BTW the ECJ 3.8 jars were not downloadable from any of the mirrors - get 404.

Only the main page has it (main page is at the bottom of show all mirrors)

srikanth-sankaran commented 1 month ago

I notice that the way this test case is set up and run, the batch compiler is not told where to find the JRE - May be that explains the observed symptom and this is not a reproducer after all ??

From help page:

Running the batch compiler From the command line. java -jar org.eclipse.jdt.core_.jar -classpath rt.jar A.java

Blush 🤦‍♂️🙈

I think I was overexcited when I saw the ever elusive message.

Although if no runtime is specified I would have expected a more direct message.

jarthana commented 1 month ago

It's not necessary to do that. But what causes this, at least with JDK 11 is that it has moved to the module system, but this is something the 3.8 ECJ doesn't understand.

Edit: I tried this with 1.8 JDK and don't see this problem. That confirms my above statement.

srikanth-sankaran commented 1 month ago

Thanks. That is a bummer. I thought we had a hot lead to go after. The self referential nature of the test setup may have clouded my initial analysis.

srikanth-sankaran commented 1 month ago

@stephan-herrmann do you agree that this reproducer is not interesting ? Before I close a confirmation would be useful. TIA

stephan-herrmann commented 1 month ago

To make sure we're on the same page, this seems to be the bare-bones error scenario:

$ echo "public class X {}" > X.java
$ java/jdk-20/bin/java -classpath ecj/ecj-3.8.jar org.eclipse.jdt.internal.compiler.batch.Main X.java
----------
1. ERROR in /tmp/X.java (at line 1)
        public class X {}
        ^
The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files
----------
2. ERROR in /tmp/X.java (at line 1)
        public class X {}
                     ^
Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
----------
2 problems (2 errors)

Right?

Starting with ecj-4.7.1a.jar no error is shown, i.e., this is the first version where it works:

Eclipse Compiler for Java(TM) v20171007-0855, 3.13.50, Copyright IBM Corp 2000, 2015. All rights reserved.

Also the combination of ecj-3.8.jar and JDK 8 works.

With that, absence of j.l.Object is no surprise in that particular combination. The only potential improvement I could imagine would be to give a better error message but that would need to be changed in maintenance versions older than 7 years, which is not going to happen.

Ergo, closing is indeed the only action I can see :)

srikanth-sankaran commented 1 month ago

Seldom do I feel so disappointed when a ticket gets closed :-(