ops4j / org.ops4j.pax.exam

Pax Exam is an in-container testing framework for OSGi
https://ops4j1.jira.com/wiki/spaces/PAXEXAM4/
Apache License 2.0
84 stars 100 forks source link

Native Container should try to isolate the Framework classloader from the system classloader [PAXEXAM-249] #376

Open ops4j-issues opened 13 years ago

ops4j-issues commented 13 years ago

Marcel Hanser created PAXEXAM-249

native container runner starts with a dependency filled system classloader. This leads to hard tracable problems with (mostly hybrid) bundles which using first the system classloader for reflection. E.g. the combination of eclipse link with the corresponding apache aries adapter behave different in a pax exam native container as in a blank felix.

(may be related to PAXEXAM-81 )


Affects: 2.0.0-RC4, 2.2.0 Fixed in: unscheduled Votes: 0, Watches: 1


Referenced issues

is related from:

ops4j-issues commented 13 years ago

Harald Wellmann commented

It is true that some tests may behave differently or even fail when running in the Native container compared to the Pax Runner container. I had a similar effect in a test with OpenJPA 2.1.0 and Aries JPA 0.3.

This is not necessarily a defect in Pax Exam. When you move from the plain old classpath to modular development with OSGi, you will discover that some libraries break because they mess around with Class.forName() which is a no-go in OSGi and a bad idea anyway.

Similarly, when you move from Pax Runner Container to Native Container, the OSGi framework is no longer running in its own VM, there are some bits of Pax Exam that use the official OSGi FrameworkFactory API to launch an embedded framework. In this scenario, the system classloader necessarily contains some other application classes on top of the OSGi framework classes.

Any OSGi framework should take care to set up boot delegation and the parent classloader for bundle classloaders correctly. Equinox gives you some extra control by means of osgi.* system properties.

But even so, there is no way to protect you from bundles in your system calling ClassLoader.getSystemClassloader() directly and thus bypassing the classloader hierarchy carefully set up by the framework.

This is what happens in Aries JPA 0.3 where the BundleDelegatingClassLoader which should load entity classes from application bundles inadvertently works with parent delegation, using the system classloader as its parent, so if you use your entity classes in your Pax Exam test, they will be loaded from the application classloader and not from the bundle classloader.

This class has been reworked substantially on Aries trunk, so I hope this issue will be fixed with the next Aries JPA release.

ops4j-issues commented 13 years ago

Marcel Hanser commented

Hi Harald. Sry, sry for my late answer.
Yep i know the problem and i'm with you... but this is a big problem when using the pax exam native container... If i add a new library to my runtime i cannot be sure that my integration test will behave as in a usual started OSGi container, this makes the native container not usable for most of my projects... their should be at least a hint or a warning in the pax exam documentation about this problem.

ops4j-issues commented 13 years ago

Toni Menzel commented

Quick comment on that:it hast Bern Reporter by peter from neo4j (Fournet peter) as well just before my ovacation.
actially this needs to be addressed using classloader Isolation when setting
up the container. No way around it. Its a common req ment when embeddding osgi in non virgin VMs.
Sorry for brevity,writing from mobile.
Toni

ops4j-issues commented 13 years ago

Toni Menzel commented

Need to stay away from commenting in jira when not actually seeing what i am typing. Sorry. Hope the point is clear anyway..:wink:

ops4j-issues commented 13 years ago

Harald Wellmann commented

@Marcel: I've added a section to the Pax Exam FAQ about this:
http://team.ops4j.org/wiki/display/paxexam/FAQ
Thought I'd done so some time ago, but evidently I hadn't :wink:

@Toni: I'm not aware of any method to achieve 100 % "classloader isolation". We may try to invoke the FrameworkFactory from a classloader that only sees the framework JAR and has the boot classloader as parent, but even in that case, bundles may break out of this jail by calling ClassLoader.getSystemClassloader(), which is bad practice of course, but I don't think we can prevent that.

ops4j-issues commented 13 years ago

Toni Menzel commented

Well, at least one can try tweaking the TCL properly which helps to cut the usual threats. Yes, clients can still break out but its then bad behaviour on purpose. I think its just important to limit the possible pitfalls. Currently NativeContainer does not do anything about it - which is just not enough.

ops4j-issues commented 13 years ago

Harald Wellmann commented

Ok, then I think we all agree: There is no 100 % solution, but we should try to provide as much isolation as we can, which is more than what we're doing now.

The question is, is there a generic approach we can implement in Native Container, or does this depend too much on framework specific configuration options?

E.g. Equinox has options

osgi.frameworkParentClassloader
osgi.contextClassLoaderParent

and by default sets the TCCL to its own ContextLoader (can't remember the exact classname).

With Felix, the TCCL for bundles is just the app classloader.

ops4j-issues commented 11 years ago

Christoph Läubrich commented

I think messing around with the TCL would just introduce other kinds of problem. I agree with Harald, that this is only an issue of wrong defined libs. I'm already has larger OSGi apps running in NativeMode without any problem, and if someone is forced to use "bad citizen" libs he can always choose to use the forked container.

The real cause (in the case that i encountered with a project using hibernate recently) the real cause is, that too much jars are considered as the boot classpath when running unittest because all the dependencies of the testclass are considered "required" even if the will be provided by the framework.