DeploymentClassLoader performance

2005-12-30 Thread Steve Molloy
Hi,

I'm trying to convert my previous axis services to axis2 to take
advantage of the async functionalities. Anyhow, I found that the
DeploymentClassLoader used offers very poor performance because it has
to go through all the lib jars for every class even when loading
multiple classes in the same jar all at once. So, I patched my class
using the 0.93 sources. Basically, while it loads the list, it also
loads the content and puts it in a HashMap so that it can directly
define the classes when needed, freeing the memory at the same time. It
does mean that unused classes in the lib jars will have their bytecode
use up memory for nothing, but the gain in performance was more then
wort it, at least in my case. I've attached the modified java file, hope
it can help...

Steve
/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.axis2.deployment;

import org.apache.axis2.i18n.Messages;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class DeploymentClassLoader extends URLClassLoader {

//urls which gives to create the classLoader
private URL[] urls;

//To keep jar files inside /lib directory in the main jar
private ArrayList lib_jars_list;

private HashMap loadedClass;
private HashMap loadedBytes;


/**
 * DeploymentClassLoader is exetend form URLClassLoader , and the constructor
 * has not overide the super constroctor , but has done some stuff to find out
 * jar fils inside /lib director
 *
 * @param urls   URL
 * @param parent parent classloader ClassLoader
 */
public DeploymentClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
this.urls = urls;
lib_jars_list = new ArrayList();
loadedClass = new HashMap();
loadedBytes = new HashMap();
findLibJars();
}

/**
 * This just search for jar files inside /lib dirctory and if there are any then those
 * will be added to the arraylit (only the name of the jar file)
 */
private void findLibJars() {
/**
 * though the URL array can contains one or more urls , I have only consider the
 * first one , that is this classLoader is only for Axis2 stuff and the classloader
 * is created by Deployment , so there wont be any chance to have more the one urls for
 * the URL array list
 */
File file = new File(urls[0].getFile());
try {
ZipInputStream parentZin = new ZipInputStream(new FileInputStream(file));
ZipEntry parentEntry;
String parentEntryName;
while ((parentEntry = parentZin.getNextEntry()) != null) {
parentEntryName = parentEntry.getName();
/**
 * id the entry name start with /lib and end with .jar
 * then those entry name will be added to the arraylist
 */
if (parentEntryName != null && (parentEntryName.startsWith("lib/") ||
parentEntryName.startsWith("Lib/")) &&
parentEntryName.endsWith(".jar")) {
String libjar_name = parentEntryName;
InputStream in = this.getResourceAsStream(libjar_name);
try {
ZipInputStream zin = new ZipInputStream(in);
ZipEntry entry;
String entryName ;
while ((entry = zin.getNextEntry()) != null) {
entryName = entry.getName();
if (entryName != null && entryName.endsWith(".class")) {
		String name = entryName.substring(0, entryName.length()-6).replace('/', '.');
if( !loadedClass.containsKey(name) ) {
		try
		{
			Class cla = super.findClass(name);
			loadedClass.put(name, cla);
		}
		catch( ClassNotFoundException ex ){
byte data[] = new 

[axis2] [Fwd: DeploymentClassLoader performance]

2005-12-30 Thread Sanjiva Weerawarana
Forwarding with proper prefix.

Sanjiva.
--- Begin Message ---
Hi,

I'm trying to convert my previous axis services to axis2 to take
advantage of the async functionalities. Anyhow, I found that the
DeploymentClassLoader used offers very poor performance because it has
to go through all the lib jars for every class even when loading
multiple classes in the same jar all at once. So, I patched my class
using the 0.93 sources. Basically, while it loads the list, it also
loads the content and puts it in a HashMap so that it can directly
define the classes when needed, freeing the memory at the same time. It
does mean that unused classes in the lib jars will have their bytecode
use up memory for nothing, but the gain in performance was more then
wort it, at least in my case. I've attached the modified java file, hope
it can help...

Steve
/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.axis2.deployment;

import org.apache.axis2.i18n.Messages;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class DeploymentClassLoader extends URLClassLoader {

//urls which gives to create the classLoader
private URL[] urls;

//To keep jar files inside /lib directory in the main jar
private ArrayList lib_jars_list;

private HashMap loadedClass;
private HashMap loadedBytes;


/**
 * DeploymentClassLoader is exetend form URLClassLoader , and the constructor
 * has not overide the super constroctor , but has done some stuff to find out
 * jar fils inside /lib director
 *
 * @param urls   URL
 * @param parent parent classloader ClassLoader
 */
public DeploymentClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
this.urls = urls;
lib_jars_list = new ArrayList();
loadedClass = new HashMap();
loadedBytes = new HashMap();
findLibJars();
}

/**
 * This just search for jar files inside /lib dirctory and if there are any then those
 * will be added to the arraylit (only the name of the jar file)
 */
private void findLibJars() {
/**
 * though the URL array can contains one or more urls , I have only consider the
 * first one , that is this classLoader is only for Axis2 stuff and the classloader
 * is created by Deployment , so there wont be any chance to have more the one urls for
 * the URL array list
 */
File file = new File(urls[0].getFile());
try {
ZipInputStream parentZin = new ZipInputStream(new FileInputStream(file));
ZipEntry parentEntry;
String parentEntryName;
while ((parentEntry = parentZin.getNextEntry()) != null) {
parentEntryName = parentEntry.getName();
/**
 * id the entry name start with /lib and end with .jar
 * then those entry name will be added to the arraylist
 */
if (parentEntryName != null && (parentEntryName.startsWith("lib/") ||
parentEntryName.startsWith("Lib/")) &&
parentEntryName.endsWith(".jar")) {
String libjar_name = parentEntryName;
InputStream in = this.getResourceAsStream(libjar_name);
try {
ZipInputStream zin = new ZipInputStream(in);
ZipEntry entry;
String entryName ;
while ((entry = zin.getNextEntry()) != null) {
entryName = entry.getName();
if (entryName != null && entryName.endsWith(".class")) {
		String name = entryName.substring(0, entryName.length()-6).replace('/', '.');
if( !loadedClass.containsKey(name) ) {
		try
		{
			Class cla = super.findClass(name);
			loadedClass.put(name, cla);
		}
		catch( ClassNotFoundException ex ){