OSGI ServiceTracker 和线程安全
ServiceTracker 在 OSGI 4.2 规范中被定义为线程安全类
。该类的用法非常简单。
我在互联网上找到的大多数使用 ServiceTracker 的示例都显示了如下代码片段:
ServiceInterface serviceObj = (ServiceInterface) serviceTracker.get();
if(serviceObj != null) {
// ...
// do smth with the serviceObject
// ...
}
现在我的问题是:一旦从 serviceTracker 检索到服务实现对象,就不能保证它将可用(不会空检查后立即删除)。
换句话说,即使在 if 循环内,服务对象 (serviceObj) 也很可能突然变为 null(如果相应的服务未注册),
因此我们应该始终像这样更正上面的代码:
ServiceInterface serviceObj = (ServiceInterface) serviceTracker.get();
if(serviceObj != null) {
try {
// ...
// do smth with the serviceObject
// ...
} catch(Throwable th) {
// a null-pointer exception may have occurred here!!
}
}
尽管如此,在博客(http://developers-blog.org/blog/default/2010/03/31/OSGI-Tutorial-How-to-use-ServiceTracker-to-get-Services)或书籍(Osgi In Action)谈谈这个要求...
我说得对吗?我错过了什么吗?
ServiceTracker is defined as a Thread-Safe class in the OSGI 4.2 spec
The usage of this class is pretty straight forward.
Most of the examples employing ServiceTracker I could find on the internet show a snippet of code like the following:
ServiceInterface serviceObj = (ServiceInterface) serviceTracker.get();
if(serviceObj != null) {
// ...
// do smth with the serviceObject
// ...
}
Now my question is: once the service implementation object is retrieved from the serviceTracker, there is no guarantee that it will be available (won't be removed) immediately after the null-check.
In other words, even within the if-cycle, the service object (serviceObj) may very well become null suddenly (if the corresponding service is unregistered)
Therefore we should always correct the code above like this:
ServiceInterface serviceObj = (ServiceInterface) serviceTracker.get();
if(serviceObj != null) {
try {
// ...
// do smth with the serviceObject
// ...
} catch(Throwable th) {
// a null-pointer exception may have occurred here!!
}
}
Despite of this, no examples either in blogs (http://developers-blog.org/blog/default/2010/03/31/OSGI-Tutorial-How-to-use-ServiceTracker-to-get-Services) or books (Osgi In Action) talk about this requirement...
Am I right? Am I missing something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您基本上是正确的,但是问题是是否在您自己的代码中处理异常,或者允许它将调用堆栈冒泡到某种全局处理程序。
我认识的大多数 OSGi 开发人员(包括我自己)更喜欢允许从该级别抛出异常的方法。在可能发生的每个点捕获异常会导致代码变得非常臃肿。
从某种意义上说,这触及了检查异常和非检查异常之间争论的核心。
请注意一个小修正:您的引用变量
serviceObj
在空检查后不能变为null
,因为它是局部变量,并且其他线程永远无法更改局部变量的值。但是,正如您推断的那样,服务引用可能会失效或不起作用。如果您刚刚从跟踪器检索到参考,则发生这种情况的可能性非常小。You're basically correct, however the question is whether to handle the exception in your own code or to allow it to bubble up the call stack to some kind of global handler.
Most OSGi developers that I know, and myself included, prefer the approach of allowing the exception to be thrown from this level. Catching exceptions at every point that they might occur leads to horribly bloated code.
In a sense, this goes to the heart of the debate between checked and unchecked exceptions.
Note one small correction: your reference variable
serviceObj
cannot becomenull
after the null-check since it is a local variable, and other threads can never change the value of your local variables. However, as you deduced, the service reference can become defunct or inoperative. The chances of this happening are very small though if you have only just retrieved the reference from the tracker.