2016-09-26 29 views
0

在我正在開發的一個項目中,我需要使用packageone中實現的一些方法定義一個抽象類。在包2中,抽象方法的其餘部分將在類實例化時實現。然後該實例在JavaFX webview中暴露給Javascript代碼。 (來自Oracle的在線示例 - https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafxJavafx WebView無法訪問class ...的成員,並帶有修飾符「public」

我的問題是,在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調用。

Packagetwo

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()"); 
    } 
} 

Packageone

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(真)那裏列出的解決方案實例),錯誤仍然拋出。

我也嘗試初始化並從packageone調用Javascript方法,但仍然有錯誤。

回答

0

Calls的匿名實現不作爲公共類使用,所以javascript引擎無法訪問它。

如果您在packagetwo中創建公共實現,即使作爲MainWindow中的內部類,然後創建要通過的實例,它也會按您的預期工作。

+0

現在有意義。謝謝你的答案。 – MrJman006