I am using JCEF in our application where we are creating a single instance of cef browser. The loadURL api is called to load the URLs using the cefBrowser insatance. First time when the browser is not created I am creating the browser with the given url using the createBrowser api. Once the browser is created the urls are loaded on the browser using loadUrl api. But, I have noticed that the browser doesn't load the url for the first time if I use createImmediately = true. From second time onward the browser can load the URLs. if I use createImmediately = false, everything works fine. However, the JVM crashes on CefApp dispose if I use createImmediately = false. The same issue as I raised in https://bitbucket.org/chromiumembedded/java-cef/issues/369/jcef-crash-on-re-parent-in
I want to use createImmediately = true to avoid the JVM crash issue, but due the above issue I am unable to use createImmediately = true
Please refer to the following sample code to understand the issue.
- Code: Select all
package test;
import org.cef.CefApp;
import org.cef.CefApp.CefAppState;
import org.cef.CefApp.CefVersion;
import org.cef.CefClient;
import org.cef.CefSettings;
import org.cef.OS;
import org.cef.browser.CefBrowser;
import org.cef.handler.CefAppHandlerAdapter;
import org.cef.handler.CefDisplayHandlerAdapter;
import org.cef.handler.CefLifeSpanHandlerAdapter;
import org.cef.handler.CefLoadHandlerAdapter;
import java.awt.*;
/**
* @author Chandan Talukdar
*/
public class JCEFBrowser {
private static final String[] COMMAND_LINE_ARGS =
{/*"--renderer-process-limit=1"*//*, "--disable-gpu", "--in-process-gpu"*/};
private CefClient cefClient ;
private boolean browserCreated;
private CefBrowser cefBrowser;
private static JCEFBrowser jcefBrowser;
static JCEFBrowser getBrowserInstance() {
if(jcefBrowser == null) {
jcefBrowser = new JCEFBrowser();
}
return jcefBrowser;
}
JCEFBrowser() {
initializeCefClient();
}
private void initializeCefClient() {
cefClient = getCefApp().createClient();
// The different life span phases can be captured with LifeSpanHandler
cefClient.addLifeSpanHandler(new CefLifeSpanHandlerAdapter() {
@Override
public void onAfterCreated(CefBrowser browser) {
// Browser is created and ready to load a URL
System.out.println("Browser Created: " + browser.getIdentifier());
browserCreated = true;
}
@Override
public void onAfterParentChanged(CefBrowser browser) {
System.out.println("Browser onAfterParentChanged: " + browser.getIdentifier());
}
@Override
public boolean doClose(CefBrowser browser) {
boolean result = browser.doClose();
return result;
}
@Override
public void onBeforeClose(CefBrowser browser) {
browserCreated = false;
cefBrowser = null;
}
});
cefClient.addLoadHandler(new CefLoadHandlerAdapter() {
@Override
public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
boolean canGoBack, boolean canGoForward) {
if (!isLoading) {
System.out.println("Browser loaded: " + browser.getIdentifier());
}
}
});
cefClient.addDisplayHandler(new CefDisplayHandlerAdapter() {
@Override
public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level,
String message, String source, int line) {
return true;
}
});
}
private CefApp getCefApp() {
if (CefApp.getState() != CefApp.CefAppState.INITIALIZED) {
CefSettings settings = new CefSettings();
settings.windowless_rendering_enabled = OS.isLinux();
CefApp cefApp = CefApp.getInstance(COMMAND_LINE_ARGS, settings);
CefVersion version = cefApp.getVersion();
System.out.println("Using CEF version:\n" + version);
CefApp.addAppHandler(new CefAppHandlerAdapter(COMMAND_LINE_ARGS) {
@Override
public void stateHasChanged(CefAppState cefAppState) {
if (cefAppState == CefAppState.TERMINATED) {
System.out.println("State is TERMINATED");
System.exit(0);
}
}
});
return cefApp;
} else {
return CefApp.getInstance();
}
}
private void createBrowser(String url, boolean createImmediately) {
cefBrowser = cefClient.createBrowser(url, OS.isLinux(), false);
if(createImmediately) {
cefBrowser.createImmediately();
}
}
Component getComponent() {
return cefBrowser.getUIComponent();
}
void loadURL(String url) {
if(!browserCreated) {
createBrowser(url, true);
} else {
cefBrowser.loadURL(url);
}
}
}
- Code: Select all
package test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* @author Chandan Talukdar
*/
class JCEFModal extends JFrame {
JCEFModal( String title) {
setName(title);
Component component = createUIComponents();
add(component);
setSize(800, 600);
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
dispose();
}
});
}
private Component createUIComponents() {
JCEFBrowser jcefBrowser = JCEFBrowser.getBrowserInstance();
String htmlUrl = "www.google.com";
jcefBrowser.loadURL(htmlUrl);
jcefBrowser.getComponent().setVisible(true);
return jcefBrowser.getComponent();
}
}
- Code: Select all
package test;
import org.cef.CefApp;
import javax.swing.*;
import java.awt.event.*;
/**
* @author Chandan Talukdar
*/
public class JCefExample extends JFrame {
private JCefExample(String title) {
setTitle(title);
setName(title);
JButton button = new JButton("click");
button.addActionListener(
e -> new JCEFModal("JCEFExampleModal")
);
button.setBounds(165, 135, 115, 55);
add(button);
setSize(500, 400);
setLayout(null);
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
CefApp.getInstance().dispose();
dispose();
}
});
}
public static void main(String[] args) {
new JCefExample("JCEF Example");
}
}
I am Using:
1. JCEF Version = 81.2.24.251
CEF Version = 81.2.24
Chromium Version = 81.0.4044.113
2. Java version used is 1.8.0_201-b09 and OS is Windows 10 x64 bit
Any suggestion is much appreciated. Thanks
Chandan