This document discusses the basic principles of resource management in the mBS framework.
Contents:
In a system which lacks sufficient resources, a proper management must distribute or limit the usage of the available resources among the parties in the system, due to some priority. For example, when a bundle has allocated too much memory, thus threatening the work of the rest of the components in the framework, then it must either be stopped, or - if there is a way - to prevent more memory allocation.
Different embedded systems (hardware and OS) may lack different kind of system resources: operational memory, persistent memory, threads, sockets, etc. Different VMs offer VM-specific approaches to management of such system resources, for example J9 allows management of operational memory, Jbed provides means for monitoring and management of CPU-time usage, conventional JDK1.1 allows control over thread creation. The framework provides an interface, which unites all VM-dependent resource managers.
Note: On Tao or Skelmir VM,
the mbs.threads.fix system property must be set to true
in order to use some VM-specific techniques for resource management.
Based on bundle's resource requirements and framework default values for those resources, a resource manager monitors each bundle's allocations, and when they reach undesired limits it may either refuse to give any more resources or to stop the bundle.
The active resource manager is available as a System Bundle service in the framework. You can use it to monitor current bundle resource allocations and to switch between resource contexts of bundles.
mBS offers two resource manager implementations:
Resource management is activated with the mbs.resman.enabled system
property. The resource manager implementation class is set as value to the system
property mbs.resman.class, so that the framework can instantiate
the proper resource manager for the current VM.
A bundle can declare requirements for system resources, so that it is clear how much memory, sockets, etc. it needs. During development, bundle needs of resources are analyzed and the results are incorporated in the bundle JAR. For example after passing some overloading tests, it becomes evident that the greatest portion of memory that a bundle can take is 100KB. This is put as a resource requirement in the bundle. So, if this bundle exceeds 100Kbytes memory allocation, this implies that something wrong has happened with bundle's normal operation. The framework (in this case presented by a resource manager) gives the bundle no more than the requested resources or the default maximum - whichever is less. This is a precaution in case a bundle allocates more resources than it normally does - this means that it functions improperly - and the resource manager must take some response actions to repair the bundle and/or to stop the process of resource allocation.
Rarely, there are resources, which two different VMs can manage at the same time. Hence, managed resources are separated by VMs in their description.
The resource requirements of a bundle are specified in a requirement
XML. The listing below illustrates how needed
resources should be specified in an XML:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE Resources SYSTEM "res.dtd"> <BundleRequirements> |
The XML in Listing 1 describes some resource requirements for J9 and any VM.
Currently supported resources for each VM are:
DataStorageSpace - Supported by
any VM when the Connector Version of the framework is used and by J9.BundleThreadsTip: The "Managed Resources" section describes the resource names to fill in the requirement XML.
Resource context is an abstraction for the context in which a bundle requests and uses resources. The resource manager assigns each bundle a separate resource context.
The resource manager uses the resource context abstraction to track the resources consumed by each bundle. When a request for a resource is received, the resource manager checks the resource context associated with the bundle. If the bundle owning this resource context is not allowed to get (any more) instances of this resource type, an exception is thrown.
Bundles are able to switch between different resource contexts. When a bundle calls a method of an object belonging to another bundle, it is recommended that the bundle switches to the resource context of the target object. This is specially necessary if the method is going to consume some resources. By default, switching to the resource context of the System Bundle (in other words of the framework) is not allowed.
Another switching issue is that of making a method end in the same context in which it starts.
A resource context is created just before a bundle activator is instantiated. The framework resource manager guarantees that a bundle resource context is switched on just before invoking the following methods:
BundleActivator.start() - Sets the resource context of the
bundle which is to be activated.BundleActivator.stop() - Sets the resource context of the bundle
which is to be deactivated.ServiceListener.serviceChanged() - Sets the resource context
of the ServiceListener implementation object.BundleListener.bundleChanged() - Sets the resource context
of the BundleListener implementation object.FrameworkListener.frameworkEvent() - Sets the resource context
of the FrameworkListener implementation object.ServiceFactory.getService() - Sets the resource context of
the bundle, requesting the service.ServiceFactory.unget() - Sets the resource context of the service
object, which is to be ungot.When a class is loaded by the bundle that owns it (the class is found in the bundle JAR), it is loaded in the resource context belonging to this bundle. In this way, the class static fields are loaded in the bundle resource context, not in the framework one.
The class loaders for all bundles are stored within the framework resource context.
When a bundle is uninstalled, the framework switches all referent resources to an empty resource context, which belongs to no entity. Thus, all entities that have switched to resource context of the bundle and are currently using its resources, are redirected to the empty context.
If a bundle creates too many threads or any of them consumes too much system resources, the bundle can be easily identified and sanctioned.
Switching the resource context of a thread does not assign the thread to the bundle owning the new resource context in terms of changing the count of the bundle’s active threads. Switching of the resource context has effect only on the newly requested resources by the corresponding thread.
Tip: By using the Thread Pool Manager service for short-living thread you can avoid the restrictions imposed on the number of active threads a bundle can have. In this case, the thread number is restricted by the Thread Pool Manager itself through its system properties.
A bundle indicates how many active threads it needs in its requirement XML
by including the BundleThreads resource name.
If there is no information about the threads a bundle requires, the values
of the mbs.resman.DefBundleThreads, mbs.resman.MaxBundleThreads
and mbs.resman.maxThreads system
properties are used.
The data storage space resource is the data space allocation per bundle.
Monitoring over the data storage space for every bundle is done by the storage
implementation used in the Connector
Version of the framework. On detecting that a bundle has reached its storage
space limit, the storage module throws a java.io.EOFException to
any write operation on a file in the bundle data directory. In this way the
bundle is informed that it should free some space by shrinking its data. The
Default Resource Manager only parses bundle data space requirements.
For the Standard Version of the framework and for J9 v2.x, the Default Resource Manager itself cares for limiting the data space of bundles.
The data space that a bundle requires can be declared in a bundle requirement
XML under the DataStorageSpace resource name.
If there is no requirement XML or the requirement for the data space is missing,
then the values of the mbs.resman.DefDataStorageSpace and mbs.resman.MaxDataStorageSpace
system properties are taken.
There is a special resource manager designed for J9 2.x, which handles memory spaces and bundle sockets.
On the J9 VM, the mBS framework supports allocation of memory spaces for each bundle. Memory spaces are introduced by the IBM Corporation and are included in the WebSphere Studio Device Developer (WSDD).
Overview. The concept of memory spaces concentrates around segmenting the available memory and allocating a separate piece of it for every running thread. This facilitates resource management and memory constraints. It also prevents flawed or unauthorized applications to intrude into the memory allocated for a module. For more information about the advantages and usage of memory spaces, refer to the WSDD documentation.
Specifying required memory space. A bundle may specify a requirement
for the memory space that will be allocated for it at startup. This requirement
should specified in the requirement XML file (see above) with the NewSegmentSize
and OldSegmentSize within the <VM
name="J9">
tag.
Settings. If the bundle requirement XML is not found, or it contains
illegal or corrupted information, memory space resource requirements are constructed
using the memory space system properties: mbs.resman.j9.newspacesize,
mbs.resman.j9.oldspacesize and mbs.resman.j9.maxspacesize.
Switching between memory spaces. Memory spaces are switched in a transparent way by using bundle resource contexts - by switching between resource contexts you switch between memory spaces.
Troubleshooting. When memory spaces are created for bundles, which are
not designed to work in such an environment, then it may happen that a memory
space is quickly filled up and an OutOfMemoryError is thrown. It
may occur to receive OutOfMemoryError during normal work on the
framework - the reason is that our bundles are not enabled for memory spaces.
The bundles do not switch the memory space when they invoke another bundles
code, so objects are created in the memory space of the calling thread whatever
it happens to be.
In order to guarantee normal work on a framework with memory spaces, all bundles (or at least those which rent services and resources) should implement switching logic using the Resource Manager service in the framework.
The J9 Resource Manager can limit the total number of sockets open by all bundles and the framework.
Specifying required bundle sockets. A bundle can specify the number of sockets it requires in its requirement XML using the BundleSockets resource name within the <VM name="J9"> tag.
Settings. If a bundle has no requirement XML or this XML does not contain
information about required sockets, then the values of the mbs.resman.DefBundleSockets,
mbs.resman.MaxBundleSockets, and mbs.resman.maxSockets
system properties are used.
Used resources in the framework can be viewed through the Resource Manager service of the System Bundle, from framework text console (local and Telnet) and from the mConsole.
The framework text console provides the info.resman command. In addition, when the J9 Resource Manager is used, you can inspect the memory spaces of bundles with the info.memory command.
The mConsole shows the resource requirements and allocations of each bundle. Also you can load a diagram for all bundles' allocations, so that a comparison between bundles can be made.
You can provide a custom resource manager. It must extend the com.prosyst.mbs.impl.framework.module.resman.AbstractResourceManager
public class, which implements the com.prosyst.mbs.framework.resman.ResourceManager
interface. Then, you should manifest the implementation class with the mbs.resman.class
system property.
Following is a brief description of the methods of com.prosyst.mbs.impl.framework.module.resman.AbstractResourceManager
that should be overridden by a custom resource manager:
|
The methods defined by the ResourceManager interface can be also
extended or overridden - see the API documentation for more details about them.
In addition, the following public methods and fields are provided in AbstractResourceManager:
|