问题描述
我有一个 Java SWT 应用程序,它使用多个浏览器小部件来显示 html 文档。这些 html 文档有一些 javascript 代码,通过 browserFunction 实例与 Java 代码进行通信。它曾经像魅力一样工作很长一段时间,直到突然它开始变得混乱:问题似乎是 browserFunction 没有正确注册/附加到浏览器了。
我怀疑某些 SWT 依赖项出了问题,因为我没有更改代码中的任何内容,也没有更改 SWT 版本,即库本身。事实上,当我全新安装我的 Linux(Ubuntu 20.04.1 LTS)并在运行任何更新之前运行我的程序时:它按预期工作。然后我运行了'apt-get update && apt-get upgrade',之后问题又出现了。
下面是重现问题的代码片段:`
预期行为:点击“创建浏览器”按钮创建一个浏览器小部件,加载“test.html”。然后,单击“单击此处”链接通过 browserFunction 实例从 Javascript 调用 Java 函数,并将某些内容打印到 Java 控制台。您应该能够多次单击“创建浏览器”按钮,并使用“单击此处”链接创建多个浏览器小部件。
实际行为:“单击此处”链接仅适用于您创建的第一个浏览器小部件。从第二次开始,小部件仍然创建,html页面仍然加载,但“单击此处”链接提示以下javascript错误:“找不到变量:callJavaFunction”。
配置:Ubuntu 20.04 LTS(在18.04下也试过,结果相同),openjdk 11.0.11,swt.jar 4.924版(也在最新的4.942下试过,结果相同)>
我尝试过的其他事情:卸载 libwebkitgtk-1.0-0,重新安装,安装 libwebkitgtk-3.0-0,使用 Wayland 会话而不是 Xorg,使用 Unity 桌面,使用 Mate桌面。
同样,在进行任何更新之前,我设法让它在新安装的 Ubuntu 20.04 上运行,并且没有安装除 Java 之外的任何东西。然后,运行操作系统更新使问题再次出现。我花了几个小时浏览网页,但我真的很难理解所有这些 Webkit 和 GTK 的东西。
代码如下:
公共类Testwindow扩展复合{
int y = 0;
Testwindow(Shell shell) {
super(shell,SWT.BORDER);
this.setSize(600,700);
Button button = new Button(this,SWT.PUSH);
button.setText("Create a browser");
button.setLocation(200,650);
button.pack();
button.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
}
@Override
public void widgetSelected(SelectionEvent arg0) {
createbrowser();
}
});
}
public void createbrowser() {
System.out.println("\nCreate a new browser");
browser browser = new browser(this,SWT.BORDER);
browser.setSize(500,200);
browser.setLocation(0,y);
File htmlFile = new File("test.html");
browser.setUrl(htmlFile.getAbsolutePath());
final browserFunction brf = new JavaFunction(browser,"callJavaFunction");
y = y + 200;
}
private static class JavaFunction extends browserFunction {
String name;
JavaFunction(browser browser,String name) {
super(browser,name);
this.name = name;
}
@Override
public Object function(Object[] arguments) {
System.out.println("Java called from Javascript");
if (name.equals("callJavaFunction")) {
System.out.println("function callJava with argument : "+arguments[0]);
}
return null;
}
}
}`
'test.html'中的代码如下
<html>
<head>
<script type="text/javascript">
function hello(msg){
try {
callJavaFunction(msg);
} catch(e) {
alert(e.message);
}
}
</script>
</head>
<body >
<a href="javascript:hello('link clicked')">click here</a>
</body>
</html>
...
我的主要课程如下:
public class Main {
public static void main(String[] args) {
display display = new display();
Shell shell = new Shell(display);
shell.setText("Test");
Testwindow testwindow = new Testwindow(shell);
shell.setSize(600,700);
shell.open();
while (!shell.isdisposed()) {
if (!display.readAnddispatch()) {
display.sleep();
}
}
display.dispose();
}
}
非常感谢任何可以对此有所了解的人......
解决方法
因此,我深入研究了我的更新历史记录,发现以下 4 个软件包导致了问题。降级它们会使 BrowserFunction 再次工作:
- libjavascriptcoregtk-4.0-18
- libwebkit2gtk-4.0-37
- gir1.2-webkit2-4.0
- gir1.2-javascriptcoregtk-4.0
最近从 2.30.6 版升级到 2.32.0 版是导致问题的原因。 出于某种原因,我无法恢复到 2.30.6,因为它在存储库中似乎不可用,但我可以降级到 2.28.1 版,这可以解决问题:sudo apt install PACKAGE_NAME=2.28.1- 1
然后,我使用以下命令来防止这些包再次更新:echo "PACKAGE_NAME hold" |须藤 dpkg --set-selections
在我使用我的程序的每台机器上每次全新安装后,我编写了以下 bash 脚本来处理它:
#!/bin/bash
echo "Downgrading the 4 packages to version 2.28.1-1..."
sudo apt install libjavascriptcoregtk-4.0-18=2.28.1-1 libwebkit2gtk-4.0-37=2.28.1-1 gir1.2-webkit2-4.0=2.28.1-1 gir1.2-javascriptcoregtk-4.0=2.28.1-1
echo ""
echo "Keeping those 4 packages from upgrading again..."
echo "libwebkit2gtk" && echo "libwebkit2gtk-4.0-37 hold" | sudo dpkg --set-selections
echo "libjavascriptcoregtk-4.0-18" && echo "libjavascriptcoregtk-4.0-18 hold" | sudo dpkg --set-selections
echo "gir1.2-webkit2-4.0" && echo "gir1.2-webkit2-4.0 hold" | sudo dpkg --set-selections
echo "gir1.2-javascriptcoregtk-4.0" && echo "gir1.2-javascriptcoregtk-4.0 hold" | sudo dpkg --set-selections
echo ""
echo "Checking installed versions :"
echo "libwebkit2gtk-4.0-37" && dpkg -s libwebkit2gtk-4.0-37 | grep Version
echo "libjavascriptcoregtk-4.0-18" && dpkg -s libjavascriptcoregtk-4.0-18 | grep Version
echo "gir1.2-webkit2-4.0" && dpkg -s gir1.2-webkit2-4.0 | grep Version
echo "gir1.2-javascriptcoregtk-4.0" && dpkg -s gir1.2-javascriptcoregtk-4.0 | grep Version
echo ""
echo "Checking packages marked as 'held' from future upgrades"
dpkg --get-selections | grep hold
echo ""
echo "done"
这是一个可行的解决方案,前提是那些以前的版本在存储库中仍然可用,人们可以假设在可预见的未来应该是这种情况。尽管如此,它们最终还是会消失,从长远来看是不可持续的。
我不确定这是否可以作为 Eclipse SWT 中所说的错误,但向他们标记问题似乎仍然很重要。因此,我将遵循 greg 的建议并在 Eclipse Bugzilla 中提交报告。