Today, OSGi's primary attraction is its class loaders model, which are sometimes called class loaders on steroids. The reason for this focus is because the Java class model had a completely different design goal then the one for which it is used today. Class loaders, an abstraction from where your code comes from, were added to support applets. Applets were loaded from the net and the original designers came up with the idea of a Class Loader. Very clever idea. However, over time applications on Java became bigger and designers saw how you could (ab)use class loaders to create extension mechanisms. With class loaders, you could load a set of JAR files from a directory and the use Class.forName or ClassLoader.loadClass to create objects implementing a shared interface. This model has become so prevalent that too many designers think this is a normal way to program, and not a hack. Many flock to OSGi because in the hope that it solves the many problems that this hack is causing. Though OSGi can solve many problems, several of those problems are implicit in the hack of dynamic class loading. Where OSGi provides proper metadata and strong modularity, the dynamic class loading often requires visibility to all possible JARs; clearly the opposite of modularity. In traditionaly Java, these problems also occurred and were addressed with other hacks: context loaders.
Though OSGi definitely provides an improvement over plain Java, the main attraction of class loaders are not the primary productivity booster. The use of the OSGi class loading model to alleviate problems with the the existing dynmic loading hacks is at most a band-aid. The most interesting aspect of OSGi is its service layer.
The OSGi modularity layer provides you with