Summary: | Compiler should not generate references to classes not on the classpath | ||||||
---|---|---|---|---|---|---|---|
Product: | [Eclipse Project] JDT | Reporter: | Sean Foley <Sean_Foley> | ||||
Component: | Core | Assignee: | Olivier Thomann <Olivier_Thomann> | ||||
Status: | VERIFIED FIXED | QA Contact: | |||||
Severity: | normal | ||||||
Priority: | P3 | CC: | peter_burka | ||||
Version: | 2.1 | ||||||
Target Milestone: | 2.1.1 | ||||||
Hardware: | All | ||||||
OS: | All | ||||||
Whiteboard: | |||||||
Attachments: |
|
Description
Sean Foley
2003-04-21 13:24:31 EDT
Customer reported and provided the following case. The project has a compilation error in one of the classes (missing catch clause). The customer, not being familiar with WSDD, did not notice the red X's and proceeded to attempt a target build for Palm. Somehow this caused the output below, in which jxelink is looking for java.lang.reflect.Constructor -- in a MIDP project. As soon as I fixed the compilation error, the project built for the target correctly. The PR is that WSDD gave the customer what was evidently a non-intuitive indication of the problem. Perhaps users could be warned if they try to do a target build on a project that contains build errors. (I would probably find that annoying myself, but wanted to document that the customer had reported this user-experience.) In any case, one would hope that the Log Console would have provided a better indication of the problem. C:\Program Files\IBM\Device Developer\wsdd5.0\ive\bin\jxelink -macro JRE_LIB=C:/Program Files/IBM/Device Developer/wsdd5.0/ive/lib/jclFoundation/classes.zip -macro PROJECT RT-JNI=C:\Program Files\IBM\Device Developer\workspace\RT-JNI -macro IVEHOME=C:\Program Files\IBM\Device Developer\wsdd5.0\ive -macro JRE_SRC=C:/Program Files/IBM/Device Developer/wsdd5.0/ive/lib/jclFoundation/source/source.zip -macro JRE_SRCROOT= @C:\Program Files\IBM\Device Developer\workspace\RT-JNI\palm68k\RTWrapper.jxeLinkOptions IVEL0009(A) Loaded 2 class(es) in 1 seconds. IVEL0049(A) Reduced to 2 class(es) in 0 seconds. IVEL0023(W) In method java/lang/Class/getConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constru ctor;, return type java.lang.reflect.Constructor not found. IVEL0018(W) In method com/palm/rtma/RTMAWrapper/RTMAWrapEx/startApp()V, referenced method java.lang.Class/getConstructor(Class[]) not found. IVEL0016(W) In method com/palm/rtma/RTMAWrapper/RTMAWrapEx/startApp()V, referenced class java.lang.reflect.Constructor not found. IVEL0054(A) Segment 0: 2 class(es) written, 5 resource(s) written, classes and resources require 6914 bytes ROM, 664(no JIT)/800(JIT) bytes RAM. IVEL0012(A) Generated "C:\Program Files\IBM\Device Developer\workspace\RT-JNI\palm68k\RTWrapper.jxe" in 0 seconds. IVEL0036(A) Summary: 0 error(s), 3 warning(s), 2 class(es) read, 2 class(es) written, 4 resource(s) written. IVEL0039(A) Summary: classes and resources require 6914 bytes ROM, 664(no JIT)/800(JIT) bytes RAM. C:\Program Files\IBM\Device Developer\wsdd5.0\ive\bin\jxe2prc RTMw RTWrapEx -nologo -midp -translate -compress -scale C:\Program Files\IBM\Device Developer\workspace\RT-JNI\palm68k/RTWrapper.jxe C:\Program Files\IBM\Device Developer\workspace\RT-JNI\palm68k\RTWrapper.prc ------- Additional Comment #1 From Bill Russell 2003-02-07 00:23 ------- Created an attachment (id=619) WSDD project that illustrates the problem Unzip and import project into workspace. Open wsddbuild.xml and hit "Perform Build". Observe warnings in Log Console. Fix missing catch clause in RTMAWrapEx.startApp() to make the problem go away. ------- Additional Comment #2 From Andrew Sandstrom 2003-04-20 20:37 ------- Any status? ------- Additional Comment #3 From sfoley 2003-04-21 11:51 ------- This one is still open. Frankly, I am not sure what direction this should take. With warnings such as the one below, the midlet might execute fine. It will only fail if the relevant methods are called. There is no way of knowing whether it will fail or not when it is used. Secondly, how do the java classes compile in WSDD if java.lang.reflect.Constructor cannot be found? Isn't there normally an error listed in the tasks view of WSDD? ------- Additional Comment #4 From Bill Russell 2003-04-21 12:22 ------- java.lang.reflect.Constructor isn't needed for this project. In fact, the entire reflect package is non-existent in CLDC/MIDP. I don't know why jxelink becomes convinced that this is of interest. It has nothing to do with the project in question. Part of the problem is that this is what shows up in the jxelink console output. It's totally out of left field, so it doesn't help the user at all and it even hurts by sending them on a wild goose chase. We can't (necessarily) blame jxelink for weird behavior when what we've sent it isn't self-consistent (e.g. didn't build). So we should probably warn the user when they try to send jxelink something that isn't self-consistent. I agree that we should not prevent the build, but we should probably warn. Optimally the user would be able to disable the warning in the preferences. ------- Additional Comment #5 From sfoley 2003-04-21 14:00 ------- I have tried this out and confirmed this strange behaviour. Upon investigation, I have determined that this behaviour is caused by the compiler. When the compiler fails to compile the startApp() method because of the missing catch or finally clause, it actually creates a new startApp() method that looks like: protected void startApp() throws javax.microedition.midlet.MIDletStateChangeExce ption 0 JBldc 19 (java.lang.String) "java.lang.Error" 2 JBinvokestatic 25 java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Cl ass; 5 JBiconst1 6 JBanewarray 21 java.lang.Class 9 JBdup 10 JBiconst0 11 JBldc 27 (java.lang.String) "java.lang.String" 13 JBinvokestatic 25 java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Cl ass; 16 JBaastore 17 JBinvokevirtual 31 java.lang.Class.getConstructor([Ljava.lang.Class;)Ljava .lang.reflect.Constructor; 20 JBiconst1 21 JBanewarray 33 java.lang.Object 24 JBdup 25 JBiconst0 26 JBldc 35 (java.lang.String) "Unresolved compilation problem: Syntax error on token "Display", "finally" expected " 28 JBaastore 29 JBinvokevirtual 41 java.lang.reflect.Constructor.newInstance([Ljava.lang.O bject;)Ljava.lang.Object; 32 JBcheckcast 43 java.lang.Error 35 JBathrow 36 JBpop 37 JBaconstnull 38 JBathrow 39 JBreturn Exception Table start end handler catch type ----- --- ------- ---------- 0 36 36 java.lang.Exception This can be translated into the following java code: protected void startApp() { try { Class errorClass = Class.forName("java.lang.Error"); Class params[] = new Class[] { Class.forName("java.lang.String")}; Constructor constructor = errorClass.getConstructor(params); Object args[] = new Object[] { "Unresolved compilation problem..."}; Error error = (Error) constructor.newInstance(args); throw error; } catch(Exception e) { throw null; } return; } So the compiler is creating a reference to java/lang/Class/getConstructor. Jxelink sees this reference and correctly warns the user that the reference cannot be resolved. Jxelink is not at fault here. What is provided to Jxelink is actually entirely consistent, a perfectly well-formed java class file. Frankly, I cannot see why the compiler would not generate the following code instead, if it wanted to be so smart: protected void startApp() { throw new Error("Unresolved compilation problem..."); } The compiler seems to try to account for the possibility that the constructor java.lang.Error(java.lang.String) might not exist. In so doing it assumes the existence of java.lang.reflect.Constructor. Seems ridiculous to me, since the constructor java.lang.Error(java.lang.String) is present in all java editions and profiles while java.lang.reflect.Constructor is not!! It seems to me that the compiler is really going out of its way to be generous to the user. When it cannot compile the code, it goes out of its way to generate a method that will inform the user if the user tries to run the code anyway. The problem is that it creates a method that is inconsistent with CLDC. There are two other things worth noting here: 1. I've discovered that the compiler will only generate a class file for the malformed class when selecting "rebuild all" in WSDD. WHen doing "rebuild project", no class file is produced. 2. If no class file is produced by the compiler, then when jxelink attempts to build the project, WSDD pops up a dialog box saying that warnings were generated during jxelink build phase, listing the warnings that the file RTMAWrapEx.class could not be found. This is the kind of behaviour that is being requested. This is really a compiler issue. Either it should: A) Generate code that is consistent with CLDC B) Generate no class file at all. Either way would be more informative to the user. This needs to be assigned to the relevant person in the compiler team. Created attachment 4652 [details] WSDD project illustrating problem See comment above from Bill Russell regarding this attachment (comment 2003-02-07 00:23) We should improve the way we generate the problem methods. The methods are really useful to prevent the user from having too many problems when one method cannot be compiled successfully. All dependant classes can still refer to this problem method because there is a class file for the type that contains this method. The way we do it right now is related to the fact that the error sent at runtime can be changed. If we consider that we want to throw a java.lang.Error all the time, then we can simplify the code generation and get rid of the reflection call. At least we could special case a few well-known exception types... If target exception is java.lang.Error, then inline it. Please make this change. Now a problem method looks like this: throw new Error(problemMessage); instead of a reflection call. Fixed and released in HEAD contents. Backported to 2.1 maintenance stream. Verified. Verified for 3.0M1. |