How to remove module layer in Java 9? - java

I have three modules: module-a, module-b, module-c. Module-a and module-b are in boot layer. Layer for module-c I create myself. Module-c has JPMS implementation of the service which interface is in module-a.
This is the way I create layer with module-c in module-b.
ModuleFinder finder = ModuleFinder.of(moduleCPath);
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("module-c"));
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
Then in module-b I call service from module-c. After service execution completed I don't need module-c and new created layer any more. How to remove it from JVM and release all resources? Is it enough to do layer = null;?

The module layer, the modules in the layer, and class loaders supporting the layer, are eligible to be GC'ed/unloaded when they are no longer reachable.
If you want to prove this to yourself then create a weak reference to the layer object and you should see that the reference is cleared (and queued if you are using a reference queue) when the layer is GC'ed.

An EMPTY_LAYER shall solve your use-case(from one of the comments on the question, trying to assign new HashSet<> as roots) here, wherein the references to other layers no more handled within the layer that you created :
layer = ModuleLayer.empty();
Returns the empty layer. There are no modules in the empty layer. It
has no parents.
On the thought of being able to remove a layer explicitly form the JVM, I would not probably expect such an API exposed publicly since a JVM is supposed to have at least one non-empty layer, the boot layer, that is created when the Java virtual machine is started.
And if such a method is exposed, I wonder if users can try and remove this layer as well. Though I am trying to be technically hypothetical on this part.

Related

(DataNucleus) JDO - Service / Repository Layering and #Transactional

For personal education I am currently developing a little application framework around Guice to learn-by-doing how Spring etc. work behind the scenes.
Intro
Just for the sake of context, here is what I have so far and plan to do so you get a feeling for what I try to archive:
Context (Core)
ApplicationContext/-Configuration
Modules (auto discovered, setting up the Guice bindings)
Extensions
Config: #Config
Locale: #Locale and i18n services
Resources: #Property, #Resource and some classes providing easy access to resources
Persistence: Problems - there we go!
Question
I'd like to use the JDO standard (and its reference implementation DataNucleus) for the persistence layer. Setting up the PersistenceManagerFactory was easy, so was using it in a basic manner. I am however targeting a typical service / repository layer architecture, e.g.:
Person
PersonRepository (JDO)
PersonService (Transactions, using PersonRepository)
That alone wouldn't be too hard either, but as soon as I tried properly integrating transactions into the concept I got a bit lost.
Desired
class PersonService {
#Transactional(TxType.REQUIRED)
public Set<Person> doX() {
// multiple repository methods called here
}
}
class PersonRepository {
private PersistenceManagerFactory pmf;
public Set<Person> doX() {
try (PersistenceManager pm = pmf.getPersistenceManager()) {
pm.....
}
}
}
Difficulties
DataNucleus supports RESOURCE_LOCAL (pm.currentTransaction()) as well as JTA transactions and I would like to support both as well (the user should not have to distinguish between the two outside the configuration). He should not have to bother about transaction handling anyway, that is part of the annotation's method interceptor (I guess).
I'd love to support the #Transactional (from JTA) annotation that can be placed on service layer methods. Knowing that annotation is not per-se available in JDO, I thought it could be made usable as well.
How exactly should the repository layer "speak" JDO? Should each method get a PersistenceManager(Proxy)from the PersistenceManagerFactory and close it afterwards (as in the example) or get a PersistenceManager injected (rather than the factory)? Should each method close the PersistenceManager (in both scenarios)? That would not work with RESOURCE_LOCAL transactions I guess since a transaction is bound to one PersistenceManager.
What I tried
I have a JDOTransactionalInterceptor (working with pmf.getPersistenceManagerProxy) and a JTATransactionalInterceptor (very similar to https://github.com/HubSpot/guice-transactional/blob/master/src/main/java/com/hubspot/guice/transactional/impl/TransactionalInterceptor.java working with a ThreadLocal)
Summary
I am aware that my question may not be as clear as desired and mixes the service / repository layer questions (which is my main problem I think) and transaction stuff (which I could figure out once I understand how to properly use PMF/PM in repository layer I think)
There is no scope à la RequestScoped etc. I just want the first #Transactional method call to be the starting point for that whole thing (and that is the point: Is this impossible and the PMF/PM have to be scoped before and I have to direct my thinkings into that direction?)
Thanks for any clarification / help!

Registering DirectChannelMetrics as a JMX Bean programmatically

I have a Spring integration application with several FileTailingMessageProducers and DirectMessageChannels created programmatically -- i.e. not through XML configuration, but within a ApplicationListener<ContextRefreshedEvent>. Now I would like to monitor the message channels using JMX. I guess I will have to add them using my integrationMBeanExporter.
This is what I tried:
DirectChannelMetrics directChannelMetrics = new DirectChannelMetrics(tailedLines, "tailedLines");
integrationMBeanExporter.getServer().registerMBean(directChannelMetrics, new ObjectName("d:foo=foo"));
Yet I am getting the following Exception:
javax.management.NotCompliantMBeanException: MBean class org.springframework.integration.monitor.DirectChannelMetrics does not implement DynamicMBean, and neither follows the Standard MBean conventions
It is surprising to me, that the DirectChannelMetrics does not fulfill JMX requirements, since when I look into my application with jvisualvm I can see other beans of this type registered without problems.
Any ideas?
From one side MBeanExporter does this on the matter:
return new StandardMBean(bean, ((Class<Object>) ifc));
Before registering bean as an MBean.
From other side I think your logic smells a bit. It looks abnormal to create MessageChannels at runtime. Especially those which are for the JMX export.
I can agree about dynamic FileTailingMessageProducers, but seems for me we can avoid dynamic channels with refactored logic for the predefined channels.
You could leverage Spring's MBeanExport.registerManagedResource(directChannelMetrics, new ObjectName("d:foo=foo")). Spring will generate a management interface for the instance of DirectChannelMetric class. But DirectChannelMetric class needs either to implement the Mbean/MXBean interface or to match current MBeanInfoAssembler expectations(be marked with the #ManagedResource annotation in the case of MetadataMBeanInfoAssembler or implements one of specified interfaces in the case of InterfaceBasedMBeanInfoAssembler etc).

Get an OSGi service instance from blueprint programmatically

I have a java class where I need to have full control the time and place of instantiation - therefore I can't initialize it as blueprint bean.
In the same bundle as that class I have a bean that I export as an OSGi-service. I would need to get access to that very service instance from the previously explained non-blueprint class.
I can't just perform a service lookup as there are other services implementing the same interface aswell. Creating a second (internal) instance of the service class will not work either.
So, as a recap:
Before I used blueprint, I had the service implementation as classic singleton, enabling me to register the same instance as service in the activator class that I could later access from within the bundle. But with blueprint (as far as I know) making the service class a "classic" singleton is not possible because it would not be possible for blueprint to create the service instance
I can't perform a service lookup because there is more than one service registered implementing the service interface.
My current solution is to query all services implementing the interface and looping the list to find the one thats instance of the one class I want.
BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
ServiceReference<?>[] refs = ctx.getServiceReferences(ServiceInterface.class.getName(), null);
ServiceImpl provider = null;
for (ServiceReference ref : refs) {
if (ctx.getService(ref) instanceof ServiceImpl) {
provider = (ServiceImpl) ctx.getService(ref);
}
}
But I do not really like the idea of that approach.
Is there any better way to solve that? Maybe some way to request a service instance direct from the blueprint container? I found the interface BlueprintContainer with a method to get instances by the ID they got - but again the only way to get an instance of the BlueprintContainer I found is to inject the instance in the class - where I hit the initial problem of the class not possible to be a blueprint bean again.
Just set a property when exporting the service. So you can filter for it. This way you can distinguish your service impl from the others.
I also propose to use a ServiceTracker for your service. So you do not have to handle the lookup for every call to the service. If you do not use a ServiceTracker make sure to unget the service after use.

Is it best to use type or properties to choose between OSGi Declarative Services?

I'm currently converting a piece of code from plain Java code to OSGi Declarative Services.
Original plain Java code
new AggregateServiceImpl(
new ChildServiceImpl1(),
new ChildServiceImpl2(),
new ChildServiceImpl3()
);
The classes are declared as so:
class AggregateServiceImpl implements Service
class ChildServiceImpl1 implements Service
class ChildServiceImpl2 implements Service
class ChildServiceImpl3 implements Service
So all classes implement Service, but the Aggregate implementation is capable of deferring to child Services when called upon.
AggregateServiceImpl itself does not know of the other implementations' existence. Its constructor is originally declared as:
public class AggregateServiceImpl(Service... children)
Clarification: the interface name 'Service' is intended generically and is not meant to represent an OSGi DS or Service concept.
Converting to OSGi
First I move each implementation into its own bundle. Then I declare my components (service implementations). I happen to be using bnd, so I use service annotations. For example:
#Component
class ChildServiceImpl1 implements Service
In the client class, we can look up the Service using the low level OSGi API or use DS in that bundle to create the object for us.
Problem
What's the best way of looking up a 'Service'? I want the AggregateServiceImpl but I might receive one of the ChildServiceImpls.
Is it best to use a separate service type or add a property to one of the components (e.g. "isRootService") to use as a filter when looking up ServiceReferences?
The best way is to use service registration properties
#Component
#Service
#Property(name = "service.id", value = "<some service unique ID")
class ChildServiceImpl1 implements Service{...}
When you look for some specific services you can use service filter:
bc.getServiceReferences(Service.class.getName(), "(service.id=<some value>)");
or if you like to use it in DS component as service reference:
#Reference(target = "(service.id=<some value>)", cardinality = ...)
private Service service;
If the AggregateServiceImpl is the only Service being used by other bundles, then it should be the only one you register.
From the code you have currently shown, we cannot tell if the AggregateServiceImpl class has dependencies on Service or the actual implementations.
If it has dependencies directly on other implementations, not the Service interface (as you have currently described it) the aggregate bundle should create the other implementation classes it requires directly and then register the AggregateServiceImpl as a Service.
If the other implementations need to be used elsewhere as well, then you should use properties (as you suggested) so consumers can distinguish between them. In this case, you still cannot use DS to construct your aggregate, since it doesn't have a dependencies on Service

CORBA + Tomcat 6 + Webapp classloader leak

EDIT:
I found classloader leak in my webapplication.
It boils down to 3rd party library initializing CORBA via JNDI's COS naming service and not exposing a call to cleanly shutdown JNDI's context. This leaves some CORBA related threads and other resources referencing my webapp classloader and preventing it from being garbage collected. This results in OutOfMemory Error: PermGen after few redeploys/reloads.
For now I increased the PermGen memory in JVM and it makes the intervals between server crashes longer. This obviously is not a fix but a workaround (and a poor one for that matter).
I guess my question is is there any way I can cleanly shutdown JNDI context without holding reference to it. My instincts tell me no, but maybe I don't know about some magic feature of JNDI that would allow me to get hold of that context.
So the way the 3rd party library initializes CORBA objects is something along this lines (exception handling and other details omited for brevity):
private CorbaObjectAggregate initCorba() {
InitialContext ctx = null;
CorbaObjectAggregate corbaObjects = new CorbaObjectAggregate();
ORB orb = null;
Properties env = getContextEnvironment();
String[] args = null;
orb = ORB.init(args, null);
env.put("java.naming.corba.orb", orb);
ctx = new InitialContext(env);
//a bunch of object lookups follow
corbaObjects.someCorbaObjectReference = (SomeCorbaObjectClass) ctx.lookup("somePaht");
return corbaObjects;
}
So the reference to ctx is gone after that method finishes executing...
I tried stopping the threads manually but it didn't fix the leak. I guess there are some other corba resources holding onto classloader. I suppose I could try to hunt them down in some cleanup method and free the classloader this way, but I was hoping for some cleaner solution.
Just for clarity, the 3rd party library is closed source and I can't really change it. It's also not viable option to get support form the company behind it.
That is going to be tricky to fix. There are likely to be two issues:
- classes loaded from the JAR holding a reference to the web-app class loader
- threads started by that process having the web-app class loader as their context class-loader.
Something along the following lines should help:
Move the JAR to $CATALINA_BASE/lib. That will mean that the classes are loaded by the common class loader. The down side is that they are also visible to and shared by every web application.
Find out where in your application the initialisation is triggered. Before that code executes, set the thread context class loader to the system class loader (or the parent of the current (web-app) class loader) and reset the thread context class loader after the init call. That should mean any threads created do not have the web-app class loader as the context class loader.
If threads get created at other points in time, fixing this could get very tricky, very quickly.
For some background that may help understand what is going on, see:
http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf
To see the sort of thing Tomcat does internally to work-around these issues see:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?view=annotate

Categories

Resources