免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1026 | 回复: 0
打印 上一主题 下一主题

从Jar字节数组装载类 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-11-18 23:06 |只看该作者 |倒序浏览
以前做项目需要从Jar字节数组装载类,也就是Jar文件中的类是一个组件,被放在数据库中,使用时从数据库中取出,然后装载里面的类。有个间接的方法是先将Jar从数据库中读出,然后写到本地文件做缓存,然后使用URLClassLoader从Jar文件装载类,这个方法需要本地文件支持,当时想找一种直接从数据库读出Jar为字节数组,然后从字节数组状态类的方法,在Google上找了很久没找到,就自己写那一个。
// MemJarClassLoader.java

/***
Copyright 2006 bsmith@qq.com
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.
*/
// MemJarClassLoader.java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
/**
* Load Jar Package from Memory Block.
* @author bsmith@qq.com
* @date 2006-9-24 5:00:30
* @module MemJarClassLoader
*/
public class MemJarClassLoader extends ClassLoader
{
    public static void main(String[] args)
    {
    }
    private ClassLoader superLoader; // super class loader.
    private byte[] data; // memory jar data.
    private int offset; // memory jar data offset.
    private int len; // memory jar data total length.
    /**
     * create class loader object.
     * @param superLoader super class loader.
     * when class can't load from this jar memory block, eg, depended class,
     * if superLoader is not null, load it from superLoader.
     * if superLoader is null, load it from super class, super class means System Default ClassLoader.
     * NOTE: in web mode, eg, in jsp, you must set superLoader to WebContext class loader or current thread class loader,
     * so that the depended class can load successfully, and superLoader can't set to System Default ClassLoader in this mode.
     * @param data jar memory data.
     */
    public MemJarClassLoader(ClassLoader superLoader, byte[] data)
    {
        this.superLoader = superLoader;
        this.data = data;
        this.offset = 0;
        this.len = data.length;
    }
   
    /**
     * create class loader object.
     * @param superLoader super class loader.
     * when class can't load from this jar memory block, eg, depended class,
     * if superLoader is not null, load it from superLoader.
     * if superLoader is null, load it from super class, super class means System Default ClassLoader.
     * NOTE: in web mode, eg, in jsp, you must set superLoader to WebContext class loader or current thread class loader,
     * so that the depended class can load successfully, and superLoader can't set to System Default ClassLoader in this mode.
     * @param data jar memory data.
     * @param offset jar memory block offset.
     * @param len jar memory block total length.
     */
    public MemJarClassLoader(ClassLoader superLoader, byte[] data, int offset, int len)
    {
        this.superLoader = superLoader;
        this.data = data;
        this.offset = offset;
        this.len = len;
    }
   
    /**
     * load class with class name.
     * when class can't load from this jar memory block, eg, depended class,
     * if superLoader is not null, load it from superLoader.
     * if superLoader is null, load it from super class, super class means System Default ClassLoader.
     * NOTE: in web mode, eg, in jsp, you must set superLoader to WebContext class loader or current thread class loader,
     * so that the depended class can load successfully, and superLoader can't set to System Default ClassLoader in this mode.
     * @param className the class name want to load.
     * @return loaded class.
     * @throws ClassNotFoundException no class found with the class name.
     */
    public Class?> loadClass(String className) throws ClassNotFoundException
    {
        JarInputStream jarIn = null;
        // convert class name to resource path name.
        String classPath = className.replace(".", "/")+".class";
        try
        {
            // init input stream.
            ByteArrayInputStream jarDataIn = new ByteArrayInputStream(this.data, offset, len);
            jarIn = new JarInputStream(jarDataIn);
            JarEntry entry;
            // find entry of the class.
            while (null != (entry = jarIn.getNextJarEntry()))
            {
                if (entry.getName().equals(classPath))
                {
                    break;
                }
            }
            // can't find class name entry in this jar, load from super.
            if (null == entry)
            {
                // if superLoader is not null, load from it.
                if (null != superLoader)
                {
                    return superLoader.loadClass(className);
                }
                // if superLoader is null, load from default super.
                else
                {
                    return super.loadClass(className);
                }
            }
            byte[] data = null;
            // if entry size is -1(unknow), the entry is invalid or compressed entry.
            if (-1 == entry.getSize())
            {
                // load compressed entry.
                ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
                byte[] packData = new byte[2048];
                int readLen = 0;
                // read 2048 bytes one time untill EOF(-1).
                while (-1 != (readLen = jarIn.read(packData)))
                {
                    dataOut.write(packData, 0, readLen);
                }
                if (dataOut.size() = 0)
                {
                    throw new ClassNotFoundException(className);
                }
                // get data.
                data = dataOut.toByteArray();
            }
            // if data size is known, read as plain bytes.
            else
            {
                data = new byte[(int)entry.getSize()];
                if (-1 == jarIn.read(data, 0, data.length))
                {
                    throw new ClassNotFoundException(className);
                }
            }
            // init class from byte data.
            Class?> cs = defineClass(className, data, 0, data.length);
            return cs;
        }
        catch(IOException err)
        {
            throw new ClassNotFoundException(err.getMessage(), err);
        }
        finally
        {
            if (null != jarIn)
            {
                try
                {
                    jarIn.close();
                }
                catch(IOException err)
                {
                    err = null;
                }
            }
        }
    }
}
没什么其他要说的,就一点,如果是在J2EE容器里面使用,需要设置superLoader,因为J2EE容器不会使用系统默认的类加载器。

文件:
MemJarClassLoader.rar
大小:
1KB
下载:
下载


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/52224/showart_425466.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP