Archive

Posts Tagged ‘Java’

Java Observer/Observable caveat

April 23rd, 2010 jmguilla No comments

ProActive Virtual Machine Management is a project in which I am invested. In several places we needed to use the Java Observer/Observable pattern but weren’t really satisfied by the way Observers are saved, this way can leads to important memory leaks in APIs where the end user doesn’t not explicitly release objects. Indeed, all listeners are not garbagge collected just because they are in the listener list.

To avoid memory leaks, we wrote our own Observer/Obserable feature based on WeakReference. Here is the code:

NotifierAdapter class is the equivalent of Observable

public class NotifierAdapter implements Notifier {
    private ArrayList<WeakReference<NotifierListener<N, T>>> listeners = new ArrayList<WeakReference<NotifierListener<N, T>>>();
    private N notifier;
 
    protected NotifierAdapter() {
        this.notifier = (N) this;
    }
 
    public NotifierAdapter(N notifier) {
        this.notifier = notifier;
    }
 
    public void addNotifierListener(NotifierListener<N, T> listener) {
        WeakReference<NotifierListener<N, T>> weakListenerReference = new WeakReference<NotifierListener<N, T>>(listener);
        this.listeners.add(weakListenerReference);
    }
 
    public void removeNotifierListener(NotifierListener<N, T> listener) {
        for (int i = 0; i < this.listeners.size(); i++) {
            WeakReference<NotifierListener<N, T>> weakListenerReference = this.listeners.get(i);
            NotifierListener<N, T> weakListener = weakListenerReference.get();
            if ((weakListener == null) || (weakListener == listener)) {
                this.listeners.remove(weakListenerReference);
            }
        }
    }
 
    public void fire(T event) {
        ArrayList<WeakReference<NotifierListener<N, T>>> toDelete = new ArrayList<WeakReference<NotifierListener<N, T>>>();
        for (WeakReference<NotifierListener<N, T>> weakListenerReference : listeners) {
            NotifierListener<N, T> weakListener = weakListenerReference.get();
            if (weakListener == null) {
                toDelete.add(weakListenerReference);
            } else {
                weakListener.update(this.notifier, event);
            }
        }
        listeners.removeAll(toDelete);
    }
}

The equivalent of the Observer interface: NotifierListener

public interface NotifierListener {
    public void update(N notifier, T event);
}

And the Notifier interface

public interface Notifier {
    public void addNotifierListener(NotifierListener listener);
 
    public void removeNotifierListener(NotifierListener listener);
 
    public void fire(T event);
}
Categories: Java, Programming Tags: ,

WMI – WBEM – Microsoft Hyper-V from Java – Linux

April 21st, 2010 jmguilla 19 comments

Hyper-V Management API

Hyper-V, take the control from your Java code.

We cannot say that there is a particular API allowing remotely manage Microsoft Hyper-V. Microsoft simply inserted new components related to virtualization to its existing WMI interface. WMI is Microsoft’s WBEM implementation using DCOM as communication layer instead of HTTP like it was planned by the standard. You can easily guess that it is really convenient for use from a Window environment but far more annoying from a Linux operating system. Here is a brief explanation about how to get that to work from a Java/Linux environment!

J-Interop, pure Java-DCOM bridge.

The solution to be able to reach a remote COM object from a Java environment is J-Interop, a pure Java-DCOM bridge. The word “pure” is used to show that there isn’t any tricky things like native Win32 library calls or anything else ( on a Linux platform, it would have been clumsy ). This API is straightforward to use, just connect to the service you want to use and call methods. You can also create new COM object on local/remote computer. Check the quickstart to see how does it work.

WMI to manage Hyper-V

As I said at the beginning, WMI is used to manage Microsoft Hyper-V environment. You can do every thing you want using this interface except actions related to file management. For example, if you play with differencing hard disks, for virtual machine clone creation ( among many possible things… ), you will be able to create files but won’t be able to delete them. To get that done, you will have to connect to default CIMV2 namespace and use CIM_Datafile class. I assume there is many other limitations in the virtualization namespace, but I haven’t found any so far. Below is an example showing how to create a new KVP exchange data item:

$ComputerName = "localhost" $VMManagementService = Get-WmiObject -class "Msvm_VirtualSystemManagementService" -namespace "root\virtualization" -ComputerName $ComputerName
$Vm = Get-WmiObject -Namespace root\virtualization -ComputerName $ComputerName -Query "Select * From Msvm_ComputerSystem Where ElementName='Vista'" $Kvp = Get-WmiObject -Namespace root\virtualization -ComputerName $ComputerName -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
 
$Msvm_KvpExchangeDataItemPath = "\\$ComputerName\root\virtualization:Msvm_KvpExchangeDataItem"
$Msvm_KvpExchangeDateItem = [WmiClass]$Msvm_KvpExchangeDataItemPath).CreateInstance()
$Msvm_KvpExchangeDateItem.Name = "bootstrapURL"
$Msvm_KvpExchangeDateItem.Data = "http://excalibur.activeeon.com:18000/"
$Msvm_KvpExchangeDateItem.Source = 0
 
$VMManagementService.AddKvpItems($Vm, $Msvm_KvpExchangeDateItem.PSBase.GetText(1))

Hyper-V’s WMI + J-Interop

Now we put every pieces together to manage Microsoft Hyper-V. Here is an example on how to connect to the Wbem service locator:

JISession session = JISession.createSession("192.168.1.166", "user", "password");
JIComServer comServer = new JIComServer(JIProgId.valueOf("WbemScripting.SWbemLocator"), "192.168.1.166", session);
IJIComObject wimObject = comServer.createInstance();
IJIDispatch locatorDispatch = (IJIDispatch) JIObjectFactory.narrowObject((IJIComObject) wimObject
        .queryInterface(IJIDispatch.IID));
Object[] params = new Object[] { new JIString(url), new JIString(namespace),
JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(),
        JIVariant.OPTIONAL_PARAM(), new Integer(0), JIVariant.OPTIONAL_PARAM() };
JIVariant[] res = locatorDispatch.callMethodA("connectServer", params);
IJIDispatch service = (IJIDispatch) JIObjectFactory.narrowObject(res[0].getObjectAsComObject());

Or here, where we print every Msvm_VirtualSwitch’s path:

import static org.jinterop.dcom.impls.JIObjectFactory.narrowObject;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
 
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.common.JISystem;
import org.jinterop.dcom.core.IJIComObject;
import org.jinterop.dcom.core.JIArray;
import org.jinterop.dcom.core.JIComServer;
import org.jinterop.dcom.core.JIProgId;
import org.jinterop.dcom.core.JISession;
import org.jinterop.dcom.core.JIString;
import org.jinterop.dcom.core.JIVariant;
import org.jinterop.dcom.impls.JIObjectFactory;
import org.jinterop.dcom.impls.automation.IJIDispatch;
import org.jinterop.dcom.impls.automation.IJIEnumVariant;
 
public class PrintVSPath {
 
        public static String domain = "DOMAIN";
	public static String url = "SERVER_NAME";
	public static String user = "USER";
	public static String pwd = "PASSWORD";
 
	public static void main(String[] args) throws JIException, SecurityException, IOException{
		JISession session = null;
		try{
			//J-Interop settings
			JISystem.getLogger().setLevel(Level.ALL);
			JISystem.setInBuiltLogHandler(false);
			JISystem.setAutoRegisteration(true);
 
			//Connection
			session = JISession.createSession(domain,user,pwd);
			JIComServer comServer = new JIComServer(JIProgId.valueOf("WbemScripting.SWbemLocator"),url,session);
			IJIComObject wimObject = comServer.createInstance();
			IJIDispatch locatorDispatch = (IJIDispatch)JIObjectFactory.narrowObject((IJIComObject)wimObject.queryInterface(IJIDispatch.IID));
			Object[] params = new Object[]{
					new JIString(url),
					new JIString("root\\virtualization"),
					JIVariant.OPTIONAL_PARAM(),
					JIVariant.OPTIONAL_PARAM(),
					JIVariant.OPTIONAL_PARAM(),
					JIVariant.OPTIONAL_PARAM(),
					new Integer(0),
					JIVariant.OPTIONAL_PARAM()
			};
			JIVariant[] res = locatorDispatch.callMethodA("connectServer",params);
			IJIDispatch sWbemServices = (IJIDispatch) JIObjectFactory.narrowObject(res[0].getObjectAsComObject().queryInterface(IJIDispatch.IID));
			res = sWbemServices.callMethodA("ExecQuery", new Object[]{
					new JIString("Select * From Msvm_VirtualSwitch"),
					JIVariant.OPTIONAL_PARAM(),
					new JIVariant(new Integer(0x10 + 0x20))
			});
			JIVariant[][] resSet = enumToJIVariantArray(res);
			IJIDispatch vsDispatch = (IJIDispatch)JIObjectFactory.narrowObject(resSet[0][0].getObjectAsComObject().queryInterface(IJIDispatch.IID));
			((IJIDispatch)JIObjectFactory.narrowObject(vsDispatch.get("Path_").getObjectAsComObject().queryInterface(IJIDispatch.IID))).get("Path").getObjectAsString2();
		}finally{
			if(session != null)
				JISession.destroySession(session);
		}
	}
 
	public static JIVariant[][] enumToJIVariantArray(JIVariant[] set) throws JIException{
		IJIDispatch toConvertDispatch = (IJIDispatch)narrowObject(set[0].getObjectAsComObject().queryInterface(IJIDispatch.IID));
		JIVariant toConvertVariant = toConvertDispatch.get("_NewEnum");
		IJIComObject toConvertComObject = toConvertVariant.getObjectAsComObject();
		IJIEnumVariant toConvertEnumVariant = (IJIEnumVariant)narrowObject(toConvertComObject.queryInterface(IJIEnumVariant.IID));
		ArrayList<JIVariant[]> res = new ArrayList<JIVariant[]>();
		int i = 0, threshold = 1000000; //to avoid infinite loop, in both msdn and j-interop nothing is said about enumeration
		while(true){
			Object[] values = null;
			try{
				values = toConvertEnumVariant.next(1);
			}catch(JIException e){
				break;
			}
			if(values != null){
				JIArray array = (JIArray) values[0];
				res.add((JIVariant[])array.getArrayInstance());
			}
			i++;
			if( i >= threshold){
				break;
			}
		}
		return res.toArray(new JIVariant[res.size()][]);
	}
}

Run a JVM on bare metal hypervisor

April 20th, 2010 jmguilla No comments

Oracle WebLogic Suite Virtualization Option

How to leverage virtualization for your enterprise software deployment?

Yesterday Oracle published a press release where it announced the availability of “Oracle WebLogic Suite Virtualization Option”. They packaged a special virtual appliance allowing to run JRockit JVM on bare metal hypervisor, Oracle VM Server, without the need of an underlying Operating System. This makes me reminisce about LiquidVM, a former BEA project.

I think this is really promising, ProActive application deployments and RM resource usage could benefit.