RMI Server herunterfahren

Hatschi

Aktives Mitglied
Folgendes Skript:

Java:
import java.rmi.RemoteException;


public interface Adder extends RMC {
	public int add(int x, int y) throws RemoteException;
}
Java:
public class AdderImpl implements Adder {
	public int add(int x, int y) {
		return x+y;
	}
}
Java:
import java.rmi.NotBoundException;
import java.rmi.RemoteException;


public interface Server extends RMC {
	public void shutdown() throws RemoteException, NotBoundException;
}
Java:
import java.rmi.RemoteException;


public class ServerImpl extends ServerModel implements Server {
	public ServerImpl() throws RemoteException {
		super();
		
		export("adder", new AdderImpl());
	}
	
	
	public static void main(String[] args) throws RemoteException {
		new ServerImpl();
	}
}
Java:
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.List;
import java.util.Vector;


public abstract class ServerModel implements Server {
	public final int PORT;
	
	protected List<String> exportedObjects;
	protected Registry registry;
	
	
	public ServerModel() throws RemoteException {
		PORT = Registry.REGISTRY_PORT;
		
		LocateRegistry.createRegistry(PORT);
		registry = LocateRegistry.getRegistry();
		
		exportedObjects = new Vector<String>();
		
		ServerModel server = this;
		export("server", server);
	}
	
	
	public void shutdown() throws RemoteException {
		UnicastRemoteObject.unexportObject(registry, true);
	}
	
	
	@SuppressWarnings("unchecked")
	protected <T extends RMC> void export(String name, T rmc) throws RemoteException {
		T exportObject = (T)UnicastRemoteObject.exportObject(rmc, 0);
		T stub = exportObject;
		exportedObjects.add(name);
		registry.rebind(name, stub);
	}
}
Java:
public interface RMC extends java.rmi.Remote {}
Java:
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {
	public static void main(String[] args) throws RemoteException, NotBoundException {
		final int PORT = Registry.REGISTRY_PORT;
		final String HOST = args[0];
		
		Registry registry = LocateRegistry.getRegistry(HOST, PORT);
		Adder adder = (Adder)registry.lookup("adder");
		System.out.println(adder.add(47, 11));
		Server server = (Server)registry.lookup("server");
		server.shutdown();
	}
}

Problem: Der eigentliche Sinn dahinter (die Addition auszuführen). Wenn ich dann aber am Ende zum runterfahren des Servers "shutdown" aufrufen möchte, kommt folgender Fehler:
Code:
Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.NoSuchObjectException: object not exported
	at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
	at sun.rmi.transport.Transport$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
	at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
	at sun.rmi.server.UnicastRef.invoke(Unknown Source)
	at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
	at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
	at $Proxy1.shutdown(Unknown Source)
	at Client.main(Client.java:15)
Caused by: java.rmi.NoSuchObjectException: object not exported
	at sun.rmi.transport.ObjectTable.unexportObject(Unknown Source)
	at java.rmi.server.UnicastRemoteObject.unexportObject(Unknown Source)
	at ServerModel.shutdown(ServerModel.java:34)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
	at sun.rmi.transport.Transport$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Der selbe kommt im übrigen wenn ich die Methoden einzeln mit "lookup" suche und dann einzeln unexporten will.
Die Methoden selbest sind aber vollkommen da. Ich kann in shutdown zB noch "add" benutzen...

wtf?
 
habe ich dich richtig verstanden, dass ich statt:

Java:
LocateRegistry.createRegistry(PORT);
registry = LocateRegistry.getRegistry();
Java:
registry = LocateRegistry.createRegistry(PORT);
schreiben sollte?

Jetzt bekomm ich immerhin keinen Fehler mehr ausgespukt, aber der Server ist trotzdem noch nicht runtergefahren :-(
Muss ich noch irgendwas anderes unexporten als die Registry?
 
Zuletzt bearbeitet:
das wäre ja Pech

ganz sicher dass alles richtig funktioniert, du verwendest ja immerhin verschiedene Programme, oder?
vielleicht verwendet eines (der Server) noch den alten Source-Stand oder so,

in jedem Fall wäre es günstig, erstmal nur beim Server eine einfache main-Methode zu testen
Java:
public static void main(String[] args) {
  Registry anlegen
  Registry ausschalten
}
funktioniert das?


-------

edit: ok, hast in deiner Antwort noch was editiert, mehr weiß ich dazu auch nicht,
vielleicht ist die noch offene RMI-Verbindung ein Problem, starte beim Server einen Thread, der erst nach 5 sec alles ausschaltet 😉

und definiere 'Server herunterfahren'
Programm beenden, Computer ausschalten?
 
Zuletzt bearbeitet von einem Moderator:
nene, ich mein mit Herunterfahren nur, dass dann der RMI Thread aufhört... Das Programm also durchgelaufen ist...
Ich starte den Server mom immer in Eclipse und den Client mit der Konsole. Ich hab jetzt mal probiert nur die Registry zu starten und direkt danach wieder zu beenden, das funktioniert... Wenn ich jetzt aber noch zwischenzeitig was exportiere, dann gehts nicht mehr, dann gibs zwar keinen Fehler, der Thread läuft aber immer noch...
 
noch ne kleine Ergänzung: mit
Java:
UnicastRemoteObject.unexportObject(this, true);
geht das (also den Server selbst krieg ich weg. Den "adder" krieg ich aber nicht weg...
 
mh, ich seh schon... mir will keiner mehr antworten. Ein letzter Versuch:
Kann es sein, dass der mit ...unexport(registry, true) vielleicht doch beendet ist und sich der Thread aus irgendwelchen unerfindlichen Gründen einfach nicht beendet und ich mit "Sytem.exit(0)" nachhelfen muss?
 
Hab da eben mal schnell gegoogelt. Mehrere Seiten berichten, dass man zwar mit einem unexport etc. die Registry mundtot machen kann, der Socket jedoch nicht freigegeben wird, egal wie man es anstellt.

Ich tippe mal darauf dass ein System.exit() der einzige Ausweg ist :-(

Zumindest wenn man auf RMI angewiesen ist *mit dem Zaunpfahl wink*

Gruß
Alex
 
*Zaunpfahl-vor-den-Kopf-bekommen*: Was wäre denn ne (vernüftige) Alternative, ganz banal über Sockets kanns ja nicht sein (kann da ja nur Strings übertragen!?) und ansonsten? vlt. CORBA?

(System.exit(0) ist wirklich die Holzhammer Methode, geht zwar, wirft mir aber Fehler an den Kopf)
 

Zurück
Oben