1

我需要您对创建可作为服务运行的 Java 应用程序的建议。我正在使用 Java 服务包装器在 Windows 中将其作为服务安装和运行。我有 2 个类 ServiceApp.java 和 RMIService.java。ServiceApp 有 main 方法,RMIService 将是一个运行以接受来自客户端的连接的服务器。

现在这是我的问题。在我的 main 方法中,一旦我创建了 RMIService,主线程就会退出并且应用程序会停止,这是正确的。由于我想阻止主线程将其作为服务运行,我创建了一个 SocketServer 和 Socket 对象并调用了 Socket.accept()。这工作正常,服务正在运行,因为主线程被阻塞,但我不相信这是正确的方法。请为我提供正确的方法来做到这一点。这是一个代码片段:

public class ServiceApp {
    public static void main(String[] args) {
        System.out.println("Starting RMI server");
        {
            RMIService rmiService;
            try {
                rmiService = new RemoteServerService();
                Registry registry = LocateRegistry.createRegistry(1099); 
                registry.rebind("RMIServer", rmiService);
                System.out.println("RMI server running");
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        ServerSocket serverSocket = null;
        Socket socket = null;
        try {
            serverSocket = new ServerSocket( 7000 );
            while ( true )
            {
                socket = serverSocket.accept(); //This will block the main thread

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally
        {
            try {
                if (socket != null)
                    socket.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}

PS:我已经在 Stackoverflow 上搜索了这些问题,但找不到符合我要求的任何内容。

4

3 回答 3

2

当您导出任何远程对象(包括注册表)时,会创建一个或多个非守护程序侦听器线程来侦听相关端口。这些将阻止进程退出。你不需要做任何进一步的事情,你当然也不需要其他毫无意义的ServerSocket.

但是,您确实需要防止导出的远程对象被垃圾收集,这将取消导出它们。您需要保留对注册表和您自己的远程对象的静态引用。

于 2013-05-23T00:23:10.017 回答
0

这是使其工作的修改后的代码。感谢 EJP 的解决方案。

服务应用程序.java

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ServiceApp {
  public static RMIService rmiService;
  public static Registry registry;

    public static void main(String[] args) {
    System.out.println("Starting RMI server");
    {

        try {
            rmiService = new RMIService();
             registry = LocateRegistry.createRegistry(1099); 
            registry.rebind("RMIServer", rmiService);
            System.out.println("RMI server running");
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

  }
}

RMIService.java

import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;



public class RMIService extends UnicastRemoteObject implements IRemoteServerService
{
private static final long serialVersionUID = 1L;


public RMIService() throws RemoteException {
    super();
     // Install a security manager.
    System.setSecurityManager(new RMISecurityManager());

}
public String pingTest()
{
    return "Server says hi";
}
@Override
public boolean resetService() throws RemoteException {
    // TODO Auto-generated method stub
    return false;
}

}

远程服务器服务

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IRemoteServerService extends Remote {


boolean resetService() throws RemoteException;
String pingTest() throws RemoteException;

}

于 2013-05-23T08:37:32.680 回答
-1

如果我错了,请纠正我,但是当您将 RMIService 绑定到注册表时,您不需要阻止 main,因为 rmiservice 会被守护进程。所以你不需要阻塞主线程。

于 2013-05-22T08:14:16.053 回答