Sobald eine Instanz eines OSGi-Dienstes aus dem Bündelkontext abgerufen wird, wird sie ungültig, wenn der Dienst beendet wird.
Meine ersten Tests zeigen, dass die Dienstinstanz auch nach dem Stoppen des Servicebündels verwendet werden kann, was meinem Verständnis der dynamischen Natur von OSGi widerspricht.
Ich nehme an, das läuft darauf hinaus, was das Abrufen eines Dienstes (über ServiceTracker) aus einem anderen Bundle im OSGi-Container tatsächlich bewirkt, erstellt es eine neue Instanz oder gibt es Ihnen einen Zeiger auf die Instanz, die im Container registriert ist?
Gibt es Gefahren bei der Verwendung der Serviceinstanz, nachdem der Service gestoppt wurde?
Das ist eine sehr gute Frage, also habe ich mich in die Spezifikation vertieft, um nach einer definitiven Antwort zu suchen. Es stellt sich heraus, dass es einen ganzen Abschnitt gibt, der über dieses Problem spricht - siehe Abschnitt 5.4 Veraltete Referenzen ab Seite 132 von Kernspezifikation der OSGi Service Platform, Version 4, Version 4.2 .
Um Ihre Frage gemäß der Spezifikation zu beantworten:
Das Verhalten eines Dienstes, der nicht registriert wird, ist nicht definiert. Solche Dienste kann weiterhin ordnungsgemäß funktionieren oder eine Ausnahme nach eigenem Ermessen auslösen.
Und um mögliche Probleme zu vermeiden:
Bundles müssen auf vom Framework generierte Ereignisse warten, um alte zu bereinigen und zu entfernen Referenzen.
Die Spezifikation gibt auch einige Tipps, wie die Folgen veralteter Referenzen minimiert werden können.
Sie haben Recht damit, dass dies der dynamischen Natur von OSGi widerspricht. Ich glaube, dass es keine Garantie gibt, dass der Dienst verfügbar sein wird, obwohl sich verschiedene Implementierungen von OSGi-Containern und Diensten selbst anders verhalten können.
Wenn der Service beispielsweise mit Spring DM erstellt und registriert wurde, handelt es sich bei dem abgerufenen Service tatsächlich um einen Spring-basierten Proxy für die zugrunde liegende Implementierung, und die Implementierung kann weiterhin ausgeblendet werden. Daher kann ein Dienstverweis, der direkt auf eine Implementierung verweist, verhindern, dass das Objekt entfernt wird, während der proxybasierte Verweis dies nicht tut.
Die OSGi-Spezifikation sagt:
Bündel sind Objekte, die sichtbar sind in der normalen Anwendungsprogrammierung. Zum Beispiel: Wenn ein Bündel gestoppt wird, alle seine Dienste werden nicht registriert.
Sie sollten also keinen Service von einem gestoppten Paket erhalten können. Aber technisch gesehen ist es möglich, sie zu benutzen, zumindest solange Sie einen Verweis auf das Serviceobjekt haben (niemand kann es von Ihnen wegnehmen und es wird nicht gecallt). Aber ich denke nicht, dass es sicher ist, den Service zu nutzen. Es hängt möglicherweise von anderen Bundle-Ressourcen ab, die nicht verfügbar sind, nachdem das Bundle beendet wurde.
Einmal eine Instanz eines OSGi-Dienstes ist aus dem Bündel Kontext abgerufen wird es wird ungültig, wenn der Dienst ist gestoppt?
Nein, die Referenz selbst wird nicht ungültig. Solange etwas innerhalb des Containers es hält, kann es auch nicht GC'ed werden.
Ob dies jedoch weiterhin nützlich ist, hängt nur von der Dienstimplementierung selbst und nicht vom Container ab.
Meine ersten Tests zeigen, dass die Service-Instanz auch nach dem Beenden des Service-Pakets verwendet werden kann, was meinem Verständnis der dynamischen Natur von OSGi widerspricht.
Die Spezifikationen selbst weisen darauf hin, dass solche Referenzen nicht gehalten werden sollten, aber es liegt am Implementierer, für die korrekte Implementierung der Spezifikationen zu sorgen; bedeutet, dass es keinen Widerspruch gibt, es gibt nur die Tatsache, dass Sie Pakete implementieren und implementieren können, die sich nicht entsprechend den Spezifikationen verhalten.
Ich nehme an, dass dies darauf hinausläuft, was einen Dienst (über ServiceTracker) von einem anderen Paket abruft erstellt der OSGi-Container tatsächlich eine neue Instanz oder gibt er Ihnen einen Zeiger? zu der Instanz, die im Container registriert ist?
Der Container erstellt keine neuen Instanzen von Diensten, außer wenn eine ServiceFactory beteiligt ist (siehe Spezifikationen). Nachschlagen eines Dienstes sollte Ihnen immer einen Zeiger auf die registrierte Instanz im Container geben.
Gibt es Gefahren bei der Verwendung der Serviceinstanz, nachdem der Service gestoppt wurde?
Das hängt nur von der Service-Implementierung ab; Wenn Sie dies jedoch in einem Paket tun, erstellen Sie automatisch ein Paket, das nicht den Spezifikationen entspricht.
In der Praxis werden viele Dienste implementiert, um Ressourcen und Referenzen freizugeben, und sie werden nicht mehr richtig reagieren.
In Bezug auf Ihre Frage, ob die Verwendung einer Serviceinstanz gefährlich ist, nachdem der Service gestoppt wurde. Um aus der 4.2 Kernspezifikation (5.4 Stale Referenzen) zu zitieren:
Das Verhalten eines Dienstes, der wird unregistriert ist nicht definiert. Eine solche Dienste können weiterhin ordnungsgemäß funktionieren oder werfen Sie eine Ausnahme auf ihre Diskretion.
Ich möchte hier nicht den ganzen Abschnitt der Spezifikation zitieren, aber die folgenden Sätze sind eine gute Diskussion über die Gefahr, veraltete Referenzen zu verwenden:
Eine veraltete Referenz ist eine Referenz auf ein zugehöriges Java-Objekt an den Klassenlader eines Bündels, das gestoppt oder verknüpft ist mit einem Dienstobjekt, das nicht registriert ist. Standard Java nicht stellen Sie generische Mittel zur Verfügung, um veraltete Referenzen zu bereinigen und zu bündeln Entwickler müssen ihren Code sorgfältig analysieren, um sicherzustellen, dass er veraltet ist Referenzen werden gelöscht.
Veraltete Referenzen sind potenziell schädlich, da sie Java behindern Garbage Collector vom Ernten der Klassen und möglicherweise der Instanzen, von angehaltenen Bündeln. Dies kann zu einem deutlich erhöhten Speicher führen Verwendung und kann dazu führen, dass native Code-Bibliotheken nicht aktualisiert werden. Bündel mit Dienste werden dringend empfohlen, entweder den Service Tracker oder Deklarative Dienste.
Eine Servicereferenz sollte niemals als Referenz gespeichert werden. Sie sollten zur Laufzeit immer einen Service nachschlagen. Dies bringt Sie mit der OSGI-API in Verbindung, die jedoch nicht immer gewünscht wird.
Sehen Sie sich an - OSGI ServiceTracker - deklarative OSGI-Dienste - OSGI BluePrint - Frühling DM - Erbse - iPojo
die alle auf die Dynamik für Sie achten, die meisten von ihnen ohne OSGI API zu verwenden.
Grüße,
Leen Toelen