Уничтожение апплета через JavaScript - PullRequest
1 голос
/ 20 марта 2012

Я создал апплет, которому необходимо выполнить следующий код:

Код

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();?

Ответы [ 3 ]

2 голосов
/ 21 марта 2012

Только после того, как этот код превратился в SSCCE 1 , многие проблемы стали понятны:

  • Этот код провалился для меня безо всяких признаковиз JS.Это указывает на то, что это не имеет ничего общего с JS! . Экземпляр Example, для которого был вызван initialize(), был не таким, как этот.который был апплет!Не имело значения, обнаружил ли пользовательский интерфейс JS, он не остановил бы запущенный экземпляр.
  • accept() блокировал EDT.
  • Установка closed в trueне собирался оказывать влияние до тех пор, пока следующий клиент не подключился и код не зациклился, чтобы снова проверить значение атрибута closed.Я добился этого, вызвав ss.close() (что делает атрибут closed избыточным, но я оставил его).

BTW

  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
1 голос
/ 20 марта 2012

Я не верю, что песочница безопасности апплета позволяет вам вызывать System#exit().Даже если это произойдет, это будет плохо для пользователя, так как конечный пользователь не сможет запустить его снова, не открывая страницу в браузере.

Скорее, пусть while перехватывает на экземпляре booleanпеременная, которую вы переключаете в методе close().Например,

private boolean closed;

public void initialize() {
    while (!closed) {
        // ...
    }
}

public void close() {
    this.closed = true;
}
0 голосов
/ 20 марта 2012

попробуйте это с pastebin.com и kill-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;
        }
    });
 }
...