【问题标题】:Killing applet through javascript通过javascript杀死小程序
【发布时间】:2012-03-20 05:12:31
【问题描述】:

我创建了一个需要执行以下代码的小程序:

代码

public class Example extends JApplet {
private ServerSocket ss ;
private Socket socket;
private boolean closed;

@Override
public void init(){
    try {
        new Example().initialize();
    } catch (IOException ex) {
        Logger.getLogger(Example.class.getName()).log(Level.SEVERE, null,ex);
    }
}
public void closed(){
    System.out.println("Inside close");
    this.closed=true;
  }
public void initialize() throws IOException{
    ss =new ServerSocket(5002);
    while(!closed){
    System.out.println("Waiting to accept request");
    socket = ss.accept();
    System.out.println("Request accepted");
    } 
}}

HTML

执行小程序的 HTML 文件片段:

<script type="text/javascript" >  
 function closeCall(){  
 document.app.closed();  
 }  
 </script>  
   <body>  
<applet id="app" code="example.Example" archive="Example.jar" height="300" width="300">    
   </applet>  
   <input type="button" value="go" onClick="closeCall()" />  

问题:单击 Go 时,我的浏览器停止响应,并且 javascript 代码也没有错误。有什么方法可以调用document.app.closed();方法吗?

【问题讨论】:

  • 如果“关闭”是指希望它从页面上消失,给它一个 ID,并使用 JS 将该 ID 的“可见性”设置为“无”(检查内容在 CSS 参考中用引号括起来 - 我还没有喝咖啡)。不要试图结束虚拟机!
  • 我只注意到sockets 标签。你的意思是关闭 socket?
  • 顺便说一句,标准小程序没有close() 方法。你的具体是做什么的? Java 控制台和 JavaScript 错误报告组件中的输出是什么?你有一个可以看到小程序直播的 URL 吗?
  • @AndrewThompson 不,没有隐藏的麻烦,我也不想关闭套接字。我想从 javascript 调用 java 中的 close 方法,当我调用它时,我的浏览器停止响应。对不起,我没有可以实时查看小程序的 URL。
  • while(true){ 应该读作while(!closed){。为了尽快获得更好的帮助,请发布SSCCE。您在 Java 控制台中看到 Inside close 了吗?

标签: java javascript applet


【解决方案1】:

只有在将该代码转换为SSCCE1 之后,许多问题才变得清晰:

  • 这段代码对我来说失败了,没有任何 JS 迹象。这向我表明,这与 JS 无关!
  • 调用initialize()Example 的实例与applet 的实例不同! UI 是否检测到 JS 无关紧要,它不会停止正在运行的实例。
  • accept() 阻止了 EDT。
  • closed 设置为true 直到下一个客户端连接并且代码循环以再次检查closed 属性的值之后才会生效。我通过调用 ss.close() 来实现它(这使得 closed 属性变得多余,顺便说一句 - 但我把它留在了里面)。

顺便说一句

  1. 请考虑将来发布 SSCCE。

代码

试试这个版本:

// <applet code='Example' width=400 height=100></applet>
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.logging.*;

public class Example extends JApplet {
    private ServerSocket ss ;
    private Socket socket;
    private boolean closed;

    @Override
    public void init(){
        JButton stop = new JButton("Stop!");
        stop.addActionListener( new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                closed();
            }
        });
        add( stop );
        validate();

        Runnable r = new Runnable() {
            public void run() {
                try {
                    initialize();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }

    public void closed() {
        System.out.println("Inside close");
        closed=true;
        try {
            ss.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public void initialize() throws IOException {
        ss =new ServerSocket(5002);
        while(!closed){
            System.out.println("Waiting to accept request");
            socket = ss.accept();
            System.out.println("Request accepted");
        }
    }
}

运行

我在这个版本中添加了一个按钮,以便您可以检查它是否按预期工作没有 JavaScript(在将 JS 加入混合之前,您应该使用自己的代码进行检查)。 AppletVewer 使用源代码顶部的单行注释将代码放在屏幕上。像这样使用它:

prompt> appletviewer Example.java

典型输出

Waiting to accept request
Inside close
java.net.SocketException: socket closed
    at java.net.PlainSocketImpl.socketAccept(Native Method)
    at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
    at java.net.ServerSocket.implAccept(ServerSocket.java:462)
    at java.net.ServerSocket.accept(ServerSocket.java:430)
    at Example.initialize(Example.java:51)
    at Example$2.run(Example.java:27)
    at java.lang.Thread.run(Thread.java:662)

Tool completed successfully

【讨论】:

    【解决方案2】:

    我不相信小程序安全沙箱允许您调用System#exit()。即使这样做了,也会对用户体验不利,因为最终用户如果不在浏览器中重新打开页面就无法再次运行它。

    宁愿让while 拦截您在close() 方法中切换的boolean 实例变量。例如

    private boolean closed;
    
    public void initialize() {
        while (!closed) {
            // ...
        }
    }
    
    public void close() {
        this.closed = true;
    }
    

    【讨论】:

    • 我也试过你的代码,但我猜 socket = ss.accept();线路阻止我关闭甚至退出。有什么解决方案吗?
    • 只需设置套接字连接超时和/或在套接字上调用close()
    【解决方案3】:

    pastebin.comkill-java-applet-via-javascript 试试这个

    <script>
     document.MyApplet.killApplet();
     </script>
    
    
     public void killApplet()
     {
        AccessController.doPrivileged(new PrivilegedAction()
       {
    
            public Void run() {
                // kill the JVM
                System.exit(0);
                return null;
            }
        });
     }
    

    【讨论】:

    • 杀死JVM是完全不负责任的。如果它在任何当前的虚拟机中工作,我会感到惊讶。
    猜你喜欢
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多