I'm running into some kind race condition in a Java applet, peculiar to Google Chrome (win xp).
I'm writing the <applet>
tag into a popup window.
The problem is characterised by:
- The applet always shows fine in MS IE and Firefox.
- In Chrome The applet only displays about 50% of the time.
- When it doesn't display, the applet actually appears to be silently running perfectly from the Java console! No errors!
- The
JApplet
'sinit()
andstart()
methods are always called. isShowing()
andisDisplayable()
always returntrue
, even when the applet does not show.- When it doesn't show, the
paint()
method isn't called. - When the applet doesn't show, a tra开发者_如何学Cnsparent rectangular area (of the window background colour) where the applet should have been can be noticed when the text in the window is selected. From this I take it that the applet region is correctly placed in the window.
My code:
MyApplet.java
package mypackage;
public class MyApplet extends JApplet {
public void init(){
super.init();
getContentPane().add(new JLabel("Hello"), BorderLayout.CENTER);
System.out.println("init ok");
}
public void start() {
super.start();
System.out.println("s parent:"+this.getParent());
System.out.println("s disp:"+this.isDisplayable());
System.out.println("s showing:"+this.isShowing());
}
public void paint(Graphics g){
System.out.println("painting");
super.paint(g);
}
}
test.html
<HTML>
<SCRIPT language='JavaScript'>
var jarpath='./myjar.jar';
var classname='mypackage.MyApplet';
function opentest(){
applet=window.open('', '', "height=420,width=620");
applet.document.write(
'<html><body>'+
'<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"'+
'width=600 height=400>'+
'<param name=code value="'+classname+'">'+
'<param name=archive value="'+jarpath+'">'+
'<param name=type value="application/x-java-applet;version1.3">'+
'<COMMENT>'+
'<EMBED code="'+classname+'" archive="'+jarpath+'" ' +
'type="application/x-java-applet;version=1.3" ' +
'width=600 height=400 ' +
'>'+
'<NOEMBED>' +
'unavailable'+
'</NOEMBED>'+
'</EMBED>' +
'</COMMENT>' +
'</OBJECT>'+
'</body></html>' );
}
</SCRIPT>
<BODY>
Click here to open <A onclick="opentest()">Test</A>
</BODY>
</HTML>
Output from console
50% of the time I click on 'Test', the new window contains the 'Hello' label. The other 50% of the time, the window is blank as described. The console output seems identical when the applet loads and doesn't load. It seems blameless!
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.definition value null
security: property package.definition new value com.sun.javaws
security: property package.definition value com.sun.javaws
security: property package.definition new value com.sun.javaws,com.sun.deploy
security: property package.definition value com.sun.javaws,com.sun.deploy
security: property package.definition new value com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy,com.sun.jnlp,org.mozilla.jss
security: property package.definition value com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.definition new value com.sun.javaws,com.sun.deploy,com.sun.jnlp,org.mozilla.jss
basic: Added progress listener: sun.plugin.util.GrayBoxPainter$GrayBoxProgressListener@137c60d
basic: Plugin2ClassLoader.addURL parent called for file:/E:/Java/eclipse/MyApplet/myjar.jar
network: Cache entry not found [url: file:/E:/Java/eclipse/MyApplet/myjar.jar, version: null]
network: Cache entry not found [url: file:/E:/Java/eclipse/MyApplet/myjar.jar, version: null]
basic: Applet loaded.
basic: Applet resized and added to parent container
basic: PERF: AppletExecutionRunnable - applet.init() BEGIN ; jvmLaunch dt 145396 us, pluginInit dt 331540 us, TotalTime: 476936 us
init ok
basic: Applet initialized
basic: Removed progress listener: sun.plugin.util.GrayBoxPainter$GrayBoxProgressListener@137c60d
basic: Applet made visible
basic: Starting applet
basic: completed perf rollup
s parent:sun.plugin2.main.client.PluginEmbeddedFrame[frame0,0,0,600x400,invalid,layout=java.awt.BorderLayout,title=,resizable,normal]
s disp:true
s showing:true
basic: Applet started
basic: Told clients applet is started
Update
Thanks to Ates, trying the following timeout makes the Applet appear correctly 100% of the time.
function opentest(){
applet=window.open('', '', "height=420,width=620");
setTimeout(function () {
applet.document.write( ... ); } ,
1000 );
}
- As Ates mentions, we now see that our popup window doesn't like immediate
document.write
s! - Is this correct behaviour? Am I supposed to wait for some signal before writing to a document?
- Should I be going about this a different way? Can I add some kind of listener to know when it is safe to call
document.write()
?
applet = window.open('', '', "height=420,width=620");
applet.document.write(...
This could be where your race condition starts. You may be trying to change the document of the newly opened window without the window being properly initialized. A quick thing to try is to let the currently running JavaScript thread "breathe", by deferring the rest of the code to a dummy timeout that will run asynchronously:
applet = window.open('', '', "height=420,width=620");
setTimeout(function () {
applet.document.write(...
}, 0);
This is not necessarily the best way to resolve this issue, but it is a quick thing to try to see if this is in fact the source of the race condition.
I have had some issues with ad blockers blocking my Applets from being visible on occasion. Though it working 50/50 seems odd.
精彩评论