Community
Participate
Working Groups
For the past several versions, perhaps since the introduction of 1.5 support, Eclipse does not recompile rt.jar properly. After recompiling rt.jar with debug info and replacing the existing jar in jdk_home/jre/lib, the focus in any dialogs of a Swing application does not work. rt.jar is recompiled using the src.zip included in the JDK and then the new classes are added to rt.jar to replace those compiled by Sun. The problem appears with either 1.4.2 or 1.5.0. The problem seems to be the byte code generated is different from the byte code generated by Sun's JDK compiler. Especially in the class java.awt.KeyboardFocusManager. If that class is not replaced, then the focus is working. If one decompile the 2 different versions one will see a slight difference in the stuff surrounding sychronize()
Here's some more information: When I start up a Swing application using a Sun JDK 1.5.0_04 rt.jar compiled by the Eclipse compiler, I get an IllegalAccessError in KeyboardFocusManager.shouldNativelyFocusHeavyweight (Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time) on the line where the method synchronizes on 'heavyweightRequests'. The stack trace looks like this: KeyboardFocusManager.shouldNativelyFocusHeavyweight(Component, Component, boolean, boolean, long) line: 2247 WToolkit.eventLoop() line: not available [native method] WToolkit.run() line: 269 Thread.run() line: 595 I'm not a byte code expert, but I can tell (via jad and looking at the byte codes), that the byte codes generated by the JDK compiler and those generated by the Eclipse compiler are different for the chunk of code that synchronizes on 'heavyweightRequests'. Why this would cause an IllegalAccessError, I have no idea. :-)
Which Eclipse build number are you using ? Can you provide exact steps to reproduce ? (i.e. a simple and detailed scenario which would not work on the recompiled library). Olivier - pls investigate, and ping me once you isolated the offending pattern.
what compliance are you using? 1.5? I guess you use 1.5 for at least compiling the 1.5 source, but when you compile the 1.4 source. Are you inlining the subroutines? This could explain the difference for the synchronize code generation.
Eclipse release: 3.1.0 For the JDK 1.5.0_05 rt.jar: Compiler Compliance Level: 5.0 Use default compliance settings Include all debug information I don't know about an option for "inlining the subroutines" but I do see an option that cannot be disabled for "Inline finally blocks" For the JDK 1.4.2_09 rt.jar Compiler Compliance Level: 1.4 Use default compliance settings Include all debug information I don't know about an option for "inlining the subroutines" but I do see an option that cannot be disabled for "Inline finally blocks" The following program will re-create the problem when run with the rt.jar compiled by the Eclipse compiler: package foo; public class EclipseCompilerProblem { public static void main(String[] args) { javax.swing.JOptionPane.showConfirmDialog(null, new javax.swing.JTextField("can you type here?")); } } Execute the program and you will not be able to type in the text field - it will never take the focus. Debug the program and you will see an IllegalAccessError as described earlier. (This error is swallowed when executing the program outside the debugger; so you will not see a stack trace.) These problems do not occur when using the rt.jar compiled by the JDK compiler.
(re: comment #4) Sorry, I meant to say that, for the JDK 1.4.2_09 rt.jar, the option to "Inline finally blocks" was NOT enabled.
I cannot reproduce this using latest 3.1 maintenance build (3.1.1 candidate). This would indicate it is a dup of one of the 50 compiler issues we did resolve since 3.1.0. Brian - could you pls get Eclipse SDK Version: 3.1.1, Build id: M20050914-1235 or better and confirm the problem has been resolved ?
I compiled JDK 1.5.0_05 and 1.4.2_08 with Eclipse build M20050914-1235 and I still have the problem. When I compile rt.jar, I have the following configuration: - All errors/warnings are set to Ignore - JavaDoc comment are not processed - No Task tags For JDK 1.5.0_0x - The compiler compliance level is set to 5.0 - Inline finally block is disabled and selected For JDK 1.4.2_0x - I unchecked Inline finally block - The compiler compliance level is set to 1.4, the generated .class files and source compatibility is also set to 1.4. I added the jar xmlparserv2.jar on my build path. I make sure the JRE Library is after the source folder on the build path. Once the classes are compiled, I add them to rt.jar. I replaced the default rt.jar in my jdk_home/jre/lib directory with the new one. I ran Brian's example and I am still seeing the problem.
I just re-compiled the jdk 1.5.0_04 rt.jar with Eclipse SDK 3.1.1 stream build M20050914-1235 and the same problem occurs. Is there something else I should try or some other configuration setting you need to know about to re-create the problem? The original jdk source for KeyboardFocusManager (starting at line 2247) looks like this: synchronized (heavyweightRequests) { HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest) ((heavyweightRequests.size() > 0) ? heavyweightRequests.getLast() : null); if (focusLog.isLoggable(Level.FINEST)) { focusLog.finest("Request " + hwFocusRequest); } The decompiled JDK byte code looks like this: /*2247*/ LinkedList linkedlist = heavyweightRequests; /*2247*/ JVM INSTR monitorenter ; HeavyweightFocusRequest heavyweightfocusrequest; /*2248*/ heavyweightfocusrequest = (HeavyweightFocusRequest)(heavyweightRequests.size() <= 0 ? null : heavyweightRequests.getLast()); /*2251*/ if (focusLog.isLoggable(Level.FINEST)) /*2252*/ focusLog.finest((new StringBuilder()).append("Request ").append(heavyweightfocusrequest).toString()); The decompiled ECLIPSE byte code looks like this: /*2247*/ synchronized (heavyweightRequests) { /*2249*/ hwFocusRequest = (HeavyweightFocusRequest)(heavyweightRequests.size() <= 0 ? null : heavyweightRequests.getLast()); /*2251*/ if (focusLog.isLoggable(Level.FINEST)) /*2252*/ focusLog.finest((new StringBuilder("Request ")).append(hwFocusRequest).toString()); Obviously jad had some problems decompiling the JDK byte code, but it did not have any problems with the Eclipse byte code. Anyway, it does indicate some sort of difference....
We are investigating.
I could reproduce the problem in the debugger. It seems to be a side-effect of the code generation for the if(dbg.on) {...} statement. This is an access to a static field done by using a static variable. So we don't consider the field access to be a constant expression. We end up generating some dead code in the body of the method with: iconst_0 ifeq 41 ... The then block is never executed. If I comment out these if statements it works fine and I cannot reproduce the problem anymore. The IllegalAccessError is thrown on the access to the field dbg. It has nothing to do with the synchronize block.
Sorry about the misleading information. I guess I was paying too much attention to the line number specified by the stack trace and the fact that jad seemed to have problems centered on that same line of code; but that may have been a side-effect of the earlier code generated for the 'if(dbg.on) {...' statement(?). Anyway, is this a bug? It appears to be a regression from Eclipse 3.0, since I have not seen this problem before.
Could you please try to get rid of the if (dbg.on) {....} statement everywhere? I'd like you to confirm that this is working fine once the if statement is gone. Thanks.
Before Eclipse 3.0, we were aggressively optimizing out many of such cases, missing potential null checks along the line. Now we are a bit less optimized on unoptimal expressions (like here, when reaching a constant boolean through a non-static slot, which we flag as a warning btw). Though the generated code is unoptimal, it is still ok (though dead), and it seems that the VM cannot properly handle deadcode, and issuing an unexpected exception (complaining about a field access which it performs just fine a few lines before). Anyhow, I think I have a fix. There are more than just qualified name to fix. I also found field references and hedging on assignments.
I got rid of all the if '(dbg.on) {...}' statements and recompiled with the Eclipse compiler and things seem to work fine for me.
Ok, I take back my previous comment. Though our codegen is unoptimal in this rare situation, the problem comes from the fact we do not generate a synthetic access method when reaching the dbg field from inside the member class; and thus hit an IllegalAccessError. Only first field fragment of a qualified name exhibits this missing synthetic (in the only case its value isn't needed, but still we generate its access to get possible side effects). It is a scenario where we optimized too much during emulation, compared to our codegen strategy. Will align them (note that strategy is different in 1.3 compliant mode, where we are right to optimize out the access method, since the field access is not generated). Will not release changes to avoid deadcode generation, since we are really close to 3.1.1, and I do not want to take too much risk there. So for 3.1.1, we will address the actual problem, and in 3.2 we will also fix the dead codegen secondary issue. Fix is in QualifiedNameReference. Added InnerEmulationTest#test123. Released in 3.1 maintenance branch.
Removing [1.5] prefix in title, since bug is not 1.5 specific (affects both 1.4 and 1.4 compliance modes).
Verified with build M20050923-0800. I also checked that the acces method is used: java.awt.KeyboardFocusManager$HeavyweightFocusRequest(Component heavyweight, Component descendant, boolean temporary); 0 aload_0 [this] 1 invokespecial java.lang.Object() [21] 4 invokestatic java.awt.KeyboardFocusManager.access$0() : sun.awt.DebugHelper [33] 7 pop 8 iconst_0 9 ifeq 27 ....
Released fix in 3.2 (HEAD) stream, along with boolean optimization for codegen (all but assignment expression as this would break some definite assignment semantics). Tuned the above regression tests accordingly.
Fix will be available in HEAD for builds > 3.2m2
Thanks for the fix, I just recompiled JDK 1.4.2 and 1.5 and everything is working well. I used build 3.1.2 N20050928-0010.
Thanks for verifying