【发布时间】:2016-09-26 14:01:03
【问题描述】:
在我正在进行的一个项目中,我需要定义一个抽象类,其中包含一些在 packageone 中实现的方法。在 packagetwo 中,其余的抽象方法将在类被实例化时实现。然后该实例在 JavaFX webview 中暴露给 Javascript 代码。 (来自 Oracle 的在线示例 - https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx)
我的问题是,packagetwo 中实现的方法不能从 Javascript 环境中调用。我收到以下错误:
Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: java.lang.IllegalAccessException: Class sun.reflect.misc.Trampoline can not access a member of class packagetwo.MainWindow$1 with modifiers "public"
at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:128)
at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
at com.sun.webkit.WebPage.executeScript(WebPage.java:1439)
at javafx.scene.web.WebEngine.executeScript(WebEngine.java:982)
at packagetwo.MainWindow.makeUpCall(MainWindow.java:130)
at packagetwo.MainWindow.access$000(MainWindow.java:22)
at packagetwo.MainWindow$2.changed(MainWindow.java:83)
at packagetwo.MainWindow$2.changed(MainWindow.java:68)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:1260)
at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1371)
at javafx.scene.web.WebEngine$LoadWorker.access$1200(WebEngine.java:1253)
at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1240)
at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2400)
at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2244)
at com.sun.webkit.network.URLLoader.twkDidFinishLoading(Native Method)
at com.sun.webkit.network.URLLoader.notifyDidFinishLoading(URLLoader.java:838)
at com.sun.webkit.network.URLLoader.lambda$didFinishLoading$96(URLLoader.java:829)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.Trampoline can not access a member of class packagetwo.MainWindow$1 with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Method.invoke(Method.java:491)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at com.sun.webkit.Utilities.lambda$fwkInvokeWithContext$55(Utilities.java:94)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.webkit.Utilities.fwkInvokeWithContext(Utilities.java:94)
... 29 more
虽然在 packageone 中实现的调用方法工作正常。从 Java 调用这两组方法也可以正常工作。以下是我的课程和 Javascript 调用。
包二
package packagetwo;
import packageone.Calls;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;
public class MainWindow implements Initializable
{
@FXML
private BorderPane mainWindow;
@FXML
private WebView mainWebView;
@FXML
private AnchorPane mainWebViewLayout;
@Override
public void initialize(URL url, ResourceBundle rb)
{
Calls jc = new Calls()
{
@Override
public void aMethod1()
{
System.out.printf("Calls: Abstract Method Impl 1 Called.\n");
}
};
// Add new load complete listener.
ChangeListener<Worker.State> onLoadComplete = buildOnLoadCompleteListener(mainWebView, jc);
mainWebView.getEngine()
.getLoadWorker()
.stateProperty()
.addListener(
onLoadComplete);
// Attempt to load the current web package.
mainWebView.getEngine().load("file:///" + new File("index.html").getAbsolutePath());
}
private ChangeListener<Worker.State> buildOnLoadCompleteListener(
WebView webview, Calls javaUpCalls)
{
return new ChangeListener<Worker.State>()
{
@Override
public void changed(
ObservableValue<? extends Worker.State> ov,
Worker.State lastState, Worker.State currentState)
{
if (currentState == Worker.State.SUCCEEDED)
{
// Hook up Java up calls in the Javascript environment.
JSObject jsEnvironment = (JSObject) webview.getEngine().executeScript("window");
jsEnvironment.setMember("JavaUpCalls", javaUpCalls);
makeUpCall(webview);
}
}
};
}
private void makeUpCall(WebView webview)
{
String setUpUpCall =
"function makeAnUpCall()" +
"{" +
"if(typeof JavaUpCalls !== \"undefined\")" +
"{" +
"JavaUpCalls.method2();" +
"JavaUpCalls.aMethod1();" +
"}" +
"}";
webview.getEngine().executeScript(setUpUpCall);
webview.getEngine().executeScript("makeAnUpCall()");
}
}
一揽子
package packageone;
public abstract class Calls()
{
public abstract void aMethod1();
public void method2()
{
System.out.printf("Calls: Method 1 Called.\n");
}
}
Index.html 只是一个标准的 html 页面,它使用 <p> 表示页面已加载的标签成功加载。
知道为什么 Javascript 环境不能调用我在 packagetwo 中实现的方法吗?
编辑:
我在网上研究了一下,发现了这个 StackOverflow 问题:
我尝试了那里列出的解决方案(在 packagetwo 方法实例上调用 setAccessible(true)),但仍然抛出错误。
我也尝试过从 packageone 初始化和调用 Javascript 方法,但仍然出现错误。
【问题讨论】:
标签: javascript java javafx webview