The Resource Consumer Demo illustrates the operation of the resource manager, in particular its support for active threads and for J9 memory spaces.
The demo consists of two parts - the Timer Bundle and the Resource Consumer Bundle.
The Resource Consumer Demo consists of two bundles located in the demo/bundles directory - Timer Bundle, which contains a timer service, and Resource Consumer Bundle, which on recurrently increases the time events requested from the Timer service creating bigger and bigger objects and more and more active threads. The JARs of the Timer Bundle and the Resource Consumer Bundle, respectively, are timer.jar and resmandemo.jar.
The main directory of Resource Consumer Demo is demo/framework/resman from the Framework Professional Edition Package . The directory holds the source files, the mk generation script for rebuilding the demo, an install.txt file for installation through the Kit Manager Bundle, a readme.txt file with short description of the demo.
The Resource Consumer Demo needs the mBS framework with enabled
resource management - the
mbs.resman.enabled system property should be true, and the
ProSyst Util Bundle - it is
packed in the putil.jar JAR from the bundles directory.
On JDK 1.5 and CVM 1.1, to have restrictions over active threads, besides mbs.resman.enabled set the mbs.resman.class system property to com.prosyst.mbs.impl.framework.module.resman.jdkv15.ResourceManagerImpl.
To have both active threads and memory space size restricted, you should start
the demo on the J9 JVM. In this case, besides setting mbs.resman.enabled
to true, with the mbs.resman.class system property you should
specify the resource manager implementation corresponding to the used version
of J9 - com.prosyst.mbs.impl.framework.module.resman.j9v2.J9ResourceManager.
The Resource Consumer Demo owns an install script for easier and faster installation of its components and necessary bundles. To get more details about starting the demo through this install script, refer to "General Rules for Demos".
Following is the procedure for starting the demo bundle by bundle:
mbs.resman.enabled to true as described in the "System
Properties" document.mbs.resman.class with the
appropriate value.fw.i -s putil.jarfw.i -s ../../../demo/bundles/timer.jarfw.i -s ../../../demo/bundles/resmandemo.jar As it was mentioned above, the Resource Consumer Demo consists of two bundles, Timer Bundle and Resource Consumer Bundle. The Timer Bundle provides a Timer service, which sends to a subscribed listener time-based events after a specified period of time. The Resource Consumer Bundle is a listener for the Timer service and on receiving an event it registers for another notification each time requesting more and more memory.
Both bundles declare specific resource requirements which the framework resource manager handles.
The Java components of the Timer Bundle are placed in the demo.resman.timer.service
and in the demo.resman.timer.service.impl packages. The first package
contains the Timer (it represents the Timer service) and TimerListener
interfaces. The second package contains the bundle activator, the Timer service
implementation - TimerImpl, and an event queue class - TimerQueueNode.
The activator of the Timer Bundle is demo.resman.timer.service.impl.TimerActivator.
When the Timer Bundle is started, the start method of the activator
is called. This method checks if the Resource Manager service (com.prosyst.mbs.framework.resman.ResourceManager)
of the System Bundle is available. If this is true, the activator instantiates
demo.resman.timer.service.impl.TimerImpl and registers it in the
framework under the Timer interface.
public class TimerActivator implements BundleActivator {
. . .
public void start(BundleContext bc) throws BundleException {
. . .
resourceRef = bc.getServiceReference(ResourceManager.class.getName());
if(resourceRef == null) {
throw new RuntimeException("Resource Management Not Available!");
}
ResourceManager resManager = (ResourceManager)bc.getService(resourceRef);
timer = new TimerImpl(resManager);
timer.start();
sRegTimer = bc.registerService("demo.resman.timer.service.Timer", |
The interface of the Timer service is demo.resman.timer.service.Timer
and it is implemented by demo.resman.timer.service.impl.TimerImpl.
In general, the main method of the Timer service is notifyAfter, which demo.resman.timer.service.TimerListener
implementations call to subscribe for time events.
When called, the notifyAfter method implementation switches from
the current resource context, which is the one of the calling bundle, to the
memory space of the Timer Bundle by using the Resource Manager service. Then
the TimerListener implementation, passed as method's argument,
is added as a node into the timer queue (TimerQueueNode). After
adding the node, the demo returns to the memory space of the requester.
. . . |
When a TimerListener implementation is notified by a TimerNodeQueue
thread, the Timer Bundle switches to the listener's resource context thus creating
objects in there.
The Timer Bundle owns a requirement XML , called TimerRes.xml, in which it declares its requirements towards the J9 resource manager. In particular, these requirements are for allocating a memory space with NewSegmentSize 24000 bytes and with OldSegmentSize 18000 bytes.
<?xml version="1.0" standalone="yes"?>
<BundleRequirements>
<Resources>
<VM name="j9">
<Resource>
<Name>NewSegmentSize</Name>
<Requirement>24000</Requirement>
</Resource>
<Resource>
<Name>OldSegmentSize</Name>
<Requirement>18000</Requirement>
</Resource>
</VM>
</Resources>
</BundleRequirements> |
After the required memory from the Timer Bundle exceeds the limits settled
for a memory space in the requirement XML, an OutOfMemoryError
is thrown.
The Resource Consumer Bundle provides no services. It contains a demo.resman.timer.service.TimerListener
implementation that "eats" memory on each received event from the
Timer service. In addition, the Resource Consumer Bundle declares requirements
for active threads, which illustrates the mechanism for thread management.
The components of the Resource Consumer Bundle are placed in the demo.resman.resconsumer
package. It contains the bundle activator and the implementation of TimerListener.
The activator of the Resource Consumer Bundle is ResourceConsumerActivator.
When the bundle is started, the activator's start method is invoked.
It checks if the Timer service is registered in the framework. If the service
presents in the service registry, a service object is retrieved. Then, a TimerListener
implementation (ResourceConsumerTimerListener) object is created
and is registered to receive one notification after 2 seconds. If the Timer
service is not registered, the activator registers a service listener for it.
public class ResConsumerActivator implements BundleActivator, ServiceListener {
. . .
public void start(BundleContext bc) throws BundleException {
. . .
sRef = bc.getServiceReference(Timer.class.getName());
if (sRef != null) activate();
bc.addServiceListener(this, "(objectClass=" + Timer.class.getName() + ")");
}
. . . |
The implementation of the demo.resman.timer.service.TimerListener
interface is ResourceConsumerTimerListener. The timer
method implemented from TimerListener is called to indicate an
event coming from the Timer service. When such an event is received, ResourceConsumerTimerListener
registers again for another timer event. At every registration, the notification
event value is doubled and a piece with byte size equal to this doubled notification
event multiplied by 10000 is requested. The ResourceConsumerTimerListener
also creates a new ResourceConsumerThread thread each time the
timer method is called.
Creating bigger and bigger objects triggers the mechanism for restriction of the memory for the Timer Bundle. Creating more and more active threads provokes the mechanism for restriction of the Resource Consumer Bundle active threads.
When the size of memory space for the Resource Consumer Bundle exceeds the
one defined by the Timer Bundle, then an OutOfMemoryError is thrown.
However the bundle continues to operate as if it has called the notifyAfter
method before the OutOfMemoryError. Therefore its timer
method is invoked later. If the cycle continues long enough (about 10 minutes),
then the timer stops dumping OutOfMemoryError messages. This happens
when the Resource Consumer Bundle's memory space remains with just a few free
bytes and the timer method receives an OutOfMemoryError before
being able to add its listener again.
private Timer timer;
private volatile boolean recurrent;
protected int count = 1;
private Vector memKeeper;
private Vector threadsKeeper;
private static int size;
private static int period = 3;
private int numTh = 0;
. . .
public void timer(int event) {
if (recurrent) {
count = (count * 2) % 1000;
timer.notifyAfter(this, period, count);
}
size = 10000 * event;
try {
ResConsumerActivator.log.info("[ResConsumerTimerListener] trying to allocate " |
In a requirement XML the Resource Consumer Bundle manifests a requirement for 50 active threads. If the thread number is exceeded, then new threads won't be created.
<?xml version="1.0" standalone="yes"?> <BundleRequirements> <Resources> |