What are the situations does the JVM decide Eager loading on a class? - loading

what is the difference between lazy loading and eager loading. Under what circumstances does lazy loading and eager loading happens.

The JVM must be able to load JVM class files. The JVM class loader loads referenced JVM classes that have not already been linked to the runtime system. Classes are loaded implicitly because:
• The initial class file - the class file containing the public static void main(String args[]) method - must be loaded at startup.
• Depending on the class policy adopted by the JVM, classes referenced by this initial class can be loaded in either a lazy or eager manner.
An eager class loader loads all the classes comprising the application code at startup. Lazy class loaders wait until the first active use of a class before loading and linking its class file.
The first active use of a class occurs when one of the following occurs:
• An instance of that class is created
• An instance of one of its subclasses is initialized
• One of its static fields is initialized
Certain classes, such as ClassNotFoundException, are loaded implicitly by the JVM to support execution. You may also load classes explicitly using the java.lang.Class.forName() method in the Java API, or through the creation of a user class loader.
Based on the above rules, lazy class loading can be forced on the system.

One more possible reason of eager class loading in JVM is class verifier in examples like this:
class Demo {
public HoneyApi getApi() {
return new HoneyImp();
}
Here HoneyImpl definition will be loaded by verifier on Demo class loading in order to check that classes are compatible to not perform that check on every call.
You may try to run JVM with -noverify to exclude verifier and see that HoneyImpl is not loaded on Demo class loading anymore.
See also JVM LS 12.3.1 https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.3.1

Related

how does system bundle has access to system packages?

I'm exploring how OSGI is implemented for the last couple of weeks. I know that each bundle uses its own class loader to load its classes. As part of my investigation, I understood that parent of every bundle's class loader is null i.e boot class loader.
System.out.println("ClassInBundle class is loaded by "+ClassInBundle.class.getClassLoader());
System.out.println("ClassInBundle parent class is "+ClassInBundle.class.getClassLoader().getParent());
Output for above code which is in bundle samplebundle is
ClassInBundle class is loaded by com.sample.bundle.samplebundle [34]
ClassInBundle parent class is null
and for imports in a bundle, it maintains a map of packagename=>classloader so that it can delegate requests to the correct class loader
Bundle SB = felix.getBundleContext().getBundle(0);
List<BundleWire> sbwires=SB.adapt(BundleWiring.class).getRequiredWires(null);
List<BundleWire> li=bundle.adapt(BundleWiring.class).getRequiredWires(null);
for(BundleWire i : li){
System.out.println(i);
}
The output for the above code is
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (osgi.wiring.package=com.test.packag) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework)(version>=1.8.0)(!(version>=2.0.0))) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.2.0)(!(version>=2.0.0))) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.ee; (&(osgi.ee=JavaSE)(version=1.6)) -> [org.apache.felix.framework [0](R 0)]
As you can see in the first line of above output, the package com.test.packag is added as FelixConstants.FRAMEWORK_SYSTEMPACKAGES and the bundle samplebundle is wired to system bundle[0] for com.test.packag.
So, I wanted to understand how system bundle[0] can access system packages which are loaded by different class loader(App class loader). Not only that all the core classes of OSGI like Bundle, BundleActivator, Felix are also loaded by App class loader. So, I tried debugging the Felix code to understand whether the system bundle is delegating the loadClass() requests to App class loader. Unfortunately, while debugging I observed m_wiring variable of BundleWiringImpl class, I noticed that classloader of system bundle is null(which is not possible because boot class loader only loads java.* packages).
please correct my understanding if I'm wrong.
My questions here are
what is the class loader of system_bundle[0] and what is its parent class loader?
if the parent of the system_bundle class loader is not App class loader, is system bundle also maintaining the map of package=>classloader to load classes which are loaded by app class loader?
what exactly is the hierarchy of class loaders(bundle class loaders, system class loader, boot class loader, and app class loader)?
Thank you.
Normally the OSGi Framework (aka the System Bundle) is loaded by the application loader and therefore has visibility of everything else on the application loader, and its parents i.e. the extension loader and the boot loader.
It actually depends on how you write your launcher. You can embed OSGi into any standard Java application simply by instantiating a FrameworkFactory and using it to launch a Framework. When you do this, the OSGi framework is just another library on the classpath and it has visibility of the same set of classes as your own code.
You can make things as simple or as fancy as you like. For example you could embed an OSGi Framework into a Servlet deployed in a J2EE application server... in that case the system bundle will have visibility to all the types available in the Web Application, as controlled by the contents of WEB-INF. You could even embed an OSGi Framework into a bundle deployed to another OSGi Framework... OSGi inception!
In all these cases, the Framework can choose what set of packages to export. These packages become available to be imported by bundles inside that Framework. By default the packages exported are the standard set of JavaSE packages for the relevant JavaSE version, but you can augment with additional application-level packages.

Executing extension before SpringExtension

I'm trying to implement integration testing in my app and have test class like that:
#ExtendWith(value={MyDockerExtension.class})
#ExtendWith(value={SpringExtension.class})
#WebAppConfiguration
#ContextConfiguration(classes={...})
#TestInstance(TestInstance.LifeCycle.PER_CLASS)
public class TestClass{ ... }
Is there any way to make MyDockerExtension execute some code, before whole SpringExtension start working and generate whole Context with Configurationc classes?
I've heard that order in which we declare extensions is the key, but sadly MyDockerExtension that implements BeforeAllCallback, AfterAllCallback executes right before test method and after whole context is loaded. In that situation it's to late to start containers with docker, becuase since whole context is loaded my app already tried to connect to the container.
At first I was skeptical about the order being fixed but you're correct:
Extensions registered declaratively via #ExtendWith will be executed in the order in which they are declared in the source code.
Regarding the MyDockerExtension, you may want to look at the extension point TestInstancePostProcessor, which is called before #BeforeAll. SpringExtension implements it and I guess it's there where it sets up the application context. If you also implement it, you should be able to act before it does.

Why imported classes take precedence over bundle classes?

I know that the specification exactly defines it but cannot get what is the reason for this:
A class space is then all classes reachable from a given bundle’s class loader.
Thus, a class space for a given bundle can contain classes from:
• The parent class loader (normally java.* packages from the boot class path)
• Imported packages
• Required bundles
• The bundle's class path (private packages)
• Attached fragments
Let's assume:
A bundle declares "import-package: a"
There is a local class a.X in this bundle
There is a class a.X in another bundle
new a.X() would load the class from another bundle.
What is the reason that imported classes take precedence over bundle classes? Is it just a consequent continuation of java hierarchical class loading policy?
This is actually a core aspect of OSGi.
Sharing classes
The whole import/export mechanism is intended to let different bundles use the same class when communicating. Same in this case means not only binary equal, but loaded by the same class loader (recall that every bundle has its own class loader). If the bundle's own classes would be favored over imported ones, bundles would not be able to 'agree' on which copy of a class to use.
But... why?
Why would you have a copy of a class, which you also intend to import?
Consider a situation in which you want to do some logging, so you import org.osgi.service.log, but it's not a vital aspect, you can happily run without a LogService present. Now,
if you would only import the package, your bundle would fail to resolve, and thus fail to start, and
if you would only include the class, you would never use the other bundle's LogService class, so you cannot use the service (this is the agreeing part).
In this situation, you both import and include the class, so you can run in either situation, using your own copy when no one else has one, and sharing a copy if someone else does. You can even choose to export your copy, and let the framework decide.
As a sidenote, this is exactly the reason you should (almost) always import what you export.

How can I use BundleWiring to lookup Bundle/Class relationships (previously done via PackageAdmin)?

I'm in the process of upgrading my application the latest release of Eclipse Equinox 3.7 and associated libraries. I'm excited to have the generic support in OSGi 4.3 and digging the new Bundle.adapt() concepts. I've run into one stumbling block.
Previously, I've used PackageAdmin.getBundle(Class) to find out which bundle loaded which classes. I have to do this due to some RMI object serialization usage.
QUESTION: Is there an way to accomplish the same result, mapping Class to Bundle, using the new BundleWiring API?
I realize that PackageAdmin is probably not going away anytime soon, but I hate deprecation warnings.
Kinda embarrassed that I didn't find this the first time I looked through the document. Answering my own question for completeness.
From the core specification PDF ...
Section 3.9.9 - Finding an Object’s Bundle
There are scenarios where a bundle is required in code that has no access to a Bundle Context. For this
reason, the framework provides the following methods:
Framework Util – Through the FrameworkUtil class with the getBundle(Class) method. The
framework provides this method to allow code to find the bundle of an object without having the
permission to get the class loader. The method returns null when the class does not originate from
a bundle.
Class Loader – An OSGi framework must ensure that the class loader of a class that comes from a
bundle implements the BundleReference interface. This allows legacy code to find an object’s
bundle by getting its class loader and casting it to a BundleReference object, which provides
access to the Bundle. However, this requires the code to have the permission to access the class
loader. The following code fragment shows how to obtain a Bundle object from any object.
ClassLoader cl = target.getClassLoader();
if ( cl instanceof BundleReference ) {
BundleReference ref = (BundleReference) cl;
Bundle b = ref.getBundle();
...
}
In an OSGi system, not all objects belong to the framework. It is therefore possible to get hold of a
class loader that does not implement the BundleReference interface, for example the boot class path
loader.

WP7 Application Life Time Funcitons

I have created a custom Class Library(named it as MiEngine), in that I have created an Application class(MiEngineApp.xaml and MiEngineApp.xaml.cs). In my project(application), I have integrated the Class Library and my project's App class extends the Class Library's Application class(ie. public partial class App:MiEngineApp). I have made changes in the App.xaml also using the z name space.
I want to implement the Application life cycle methods only in the Class Library's Application class not in the project's Appication class. But If I do not implement the Application Life cycle methods in the project's Application class, at run time XamlParseException is thrown in the MiEngineApp.g.i.cs file's InitializeComponent method. I have no clue why this happens and how to implement the life cycle methods only in the Class library's Application class. Please give me some idea!
You could put the logic for the lifecycle events in the library and then call them from the event handlers in the (each?) app. Yes this means adding 4 lines of code to the app but this is the best solution currently available.
As per the default comments in app.xaml, handlers for the Launching, Activated, Deactivated and Closing events of the PhoneApplicationService are REQUIRED.

Resources