当然不能写进去。你的数据库主键或者Unique key,就是完整的类名
比如com.xyz.Test$1,
然后你覆盖java.lang.ClassLoader#findClass(java.lang.String)方法protected Class<?> findClass(String className) throws ClassNotFoundException {
    byte[] b = loadClassData(className);
    return defineClass(className, b, 0, b.length);
  }
其中loadClassData是自定义的,你去数据库里面根据完整的className读取blob即可

解决方案 »

  1.   

    protected Class<?> findClass(String className) throws ClassNotFoundException {
        byte[] b = loadClassData(className);
        return defineClass(className, b, 0, b.length);
      }
    现在的问题就出在defineClass(className, b, 0, b.length);这个里面,对于主类com.xyz.Test.calss和com.xyz.Test1.calss、com.xyz.Test2.calss我在存储的时候该怎么存储?读取的时候我用loadClassData又该怎么读取才能让defineClass(className, b, 0, b.length);不报错
      

  2.   

    3条数据啊
    com.xyz.Test
    com.xyz.Test$1
    com.xyz.Test$2
      

  3.   

    那我在用defineClass(className, b, 0, b.length);读取的时候,这个b读取的是com.xyz.Test的数据,加载该类的时候com.xyz.Test$1
    com.xyz.Test$2应该还是项目默认的包路径不会从数据库中读取Test$1和Test$2吧
      

  4.   

    class还能存到数据库的啊,牛 观摩下
      

  5.   

    这个哥们来看看,如果存成三条数据,我在读的时候怎么通过defineClass(className, b, 0, b.length);去读这三条数据,这个b是个byte数组,只读取主类的话,我觉得加载子类的话会从项目环境中去找,如果把主类和子类都放到byte数组中,会提示找不到子类Exception in thread "main" java.lang.IllegalAccessError: tried to access class com.test..FrameTest$bcliass from class com.test..FrameTest
      

  6.   

    不要你觉得如何如何。对于类加载器来说:
    com.xyz.Test
    com.xyz.Test$1
    com.xyz.Test$2
    它们是3个类。你默认的类加载器,也是去3个地方加载分3次加载,比如下面的例子,运行的时候,Test$MyThread.class根本不会被加载,除非你调用了foo之后。
    匿名类不能用static段,为了打印类加载器加载的时机,所以这里没用匿名类,但原理一样。如果一定要测试匿名类。可以在编译以后,手工删除Test$1.class,只要没有调用bar(还要先new个Test)才会报NoClassDefFoundError
    public class Test {  static {
        System.out.println("Test.<clinit>");
      }  public static void main(String[] args) {
        System.out.println("Test.main");
        // foo();
        // new Test().bar();
      }  public static void foo() {
        new MyThread().start();
      }
      public void bar() {
        new Thread() {
          public void run() {
          }
        }.start();
      }
      static class MyThread extends Thread {
        static {
          System.out.println("Test$MyThread.<clinit>");
        }
        public void run() {
          System.out.println("Test$MyThread.run");
        }
      }
    }
    }
      

  7.   

    只要没有调用bar(还要先new个Test)才会报NoClassDefFoundError
    只有调用了bar(还要先new个Test)才会报NoClassDefFoundError
      

  8.   

    匿名类和主类分开存.
    当需要某个匿名类时Java会通过ClassLoader加载, 你只要返回正确的匿名类class即可.
      

  9.   


    为何非要统一写到一个class文件中去啊,该分开放就分开呗,数据库也不是处理不了。
      

  10.   

    可能我表述的不太清楚,我是想动态替换掉项目中的类,关键代码如下:
    public class MyLoader extends ClassLoader {
           ......
            //namefile是本地class类路径,classname是项目所在的类全称,如果本地有最新的类则优先加载最新的类,如果没有则默认加载项目中的
    public Class load(String namefile, String classname) throws ClassNotFoundException {
    Class clasz = null;
    if (namefile != null) { //首先会判断本地有没有class类文件
    byte[] classData = loadClassData(namefile);//如果有则读取该类的内容
    if (classData != null) {//如果获取的class内容不为空则加载该内容
    clasz = defineClass(classname, classData, 0, classData.length);
    }
    if (clasz == null) {//如果没有则加载系统默认的类
    clasz = findSystemClass(classname);
    }
    }
    if (clasz == null) {//如果为空,依然加载系统默认的类
    clasz = loadClass(classname);
    if (clasz != null) {
    System.out.println(clasz.getName() + " is load");
    }
    }
    return clasz;
    }
           .......
             public byte[] loadClassData(String name) {//从本地的class类文件读取内容
    try {
    // 下面是定制部分,通过某种方法获取字节码数据
    System.out.print("\r\n截获:" + name + "!!!  ");
    if (name != null && name.indexOf(".jar") >= 0) {//暂时不支持jar包上传
    return null;
    } else if (name != null && name.trim().toLowerCase().indexOf(".class") >= 0) {//只支持后缀名为.class的文件
    if (new File(name).exists()) {//如果该类文件存在则加载
    System.out.println("在文件:" + name + "中发现该类,装入解密后的数据!");
    File file = new File(name);
    long len = file.length();
    byte[] return_classData = new byte[(int) len];
    FileInputStream fin = new FileInputStream(file); // 读取当前目录中C.class文件中的内容
    fin.read(return_classData); // 给return_classData数据赋值
    fin.close();
    return return_classData;
    }
    }
    System.out.println("在遍历所有的ClassPath后,均没有发现该类,返回Null");
    return null;
    } catch (Exception ex) {
    System.out.println("发生异常!");
    ex.printStackTrace();
    return null;
    }
    }
    public static void main(String args[]) {
    MyLoader loader = new MyLoader();
    String namefile = "C:/class/FrameTest.class";//本地的一个类文件
    Class class1 = null;
    Class class2 = null;
    try {
    class1 = loader.load(namefile, "cn.com.test.FrameTest");//加载本地c盘下的class类文件
    class2 = Class.forName("cn.com.test.FrameTest");//加载项目默认的class
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }

    Method[] m = class1.getDeclaredMethods();
    for (int i = 0; i < m.length; i++) {
    System.out.println(m[i].toString());//输出本地c盘下FrameTest类的所有方法
    }
    Method[] n = class2.getDeclaredMethods();
    for (int i = 0; i < n.length; i++) {
    System.out.println(n[i].toString());//输出项目编译后的FrameTest类的所有方法
    }
    }
    上面测试是在本地C盘下的class文件,存入数据库原理是一样的,如果cn.com.test.FrameTest没有匿名类或者内部类,即一个java文件编译后生成的class文件如果只有一个则不会出现问题,因为读取的都是那一个类,我先拷贝class到C盘下然后在项目中修改FrameTest类的方法,则上面输出的二者是不一样的,如果编译后生成的class类文件有两个及以上则就会出现问题,比如FrameTest.java编译后可能有FrameTest.class、FrameTest$1.class和FrameTest$bc.class,假如我依然加载FrameTest.class则相当于FrameTest$1.class和FrameTest$bc.class这两个类的内容依然用的是之前项目中的,并不是最新修改的,假如我又想加载那两个子类loadClassData这个方法又该如何读取内容,我想要解决的就是一个java文件会生成多个class类的情况,请指点
      

  11.   


    为何非要统一写到一个class文件中去啊,该分开放就分开呗,数据库也不是处理不了。
    分开倒是没问题,问题是分开后我用这段代码如何去加载有多个子类组成的类
    byte[] classData = loadClassData(namefile);//如果有则读取该类的内容
    if (classData != null) {//如果获取的class内容不为空则加载该内容
    clasz = defineClass(classname, classData, 0, classData.length);
    }
      

  12.   

    把FrameTest开头的class类全部加载上来。
      

  13.   


    为何非要统一写到一个class文件中去啊,该分开放就分开呗,数据库也不是处理不了。
    分开倒是没问题,问题是分开后我用这段代码如何去加载有多个子类组成的类
    byte[] classData = loadClassData(namefile);//如果有则读取该类的内容
    if (classData != null) {//如果获取的class内容不为空则加载该内容
    clasz = defineClass(classname, classData, 0, classData.length);
    }你呀,还是没搞清楚状况,什么时候加载Test$1.class ???
    不是加载Test.class的时候,而是用到它的时候,自然会自己去调用用它的那个类所在的类加载器,去找Test$1.class的
    Don't call us. We will call you.
      

  14.   


    为何非要统一写到一个class文件中去啊,该分开放就分开呗,数据库也不是处理不了。
    分开倒是没问题,问题是分开后我用这段代码如何去加载有多个子类组成的类
    byte[] classData = loadClassData(namefile);//如果有则读取该类的内容
    if (classData != null) {//如果获取的class内容不为空则加载该内容
    clasz = defineClass(classname, classData, 0, classData.length);
    }你呀,还是没搞清楚状况,什么时候加载Test$1.class ???
    不是加载Test.class的时候,而是用到它的时候,自然会自己去调用用它的那个类所在的类加载器,去找Test$1.class的
    Don't call us. We will call you.
    你的意思是我byte[] classData = loadClassData(namefile);//依然只读取主类,它会自动加载跟namefile这个同目录下的子类?
      

  15.   

    它跟普通的类不一样,举个例子假如              如果一个java文件编译后生成多个class文件,如果你把其它的两个子类删掉,则这个class就报错,但是如果跟你举个例子,假如项目已经上线一段时间了,客户提出需求后你只修改了一个名字叫Test.java的文件,如果这个Test.java编译后只有一个class文件,那么你只覆盖服务器上的Test.class一个文件即可,假如Test.java这个文件编译好后生成多个以Test开头的class文件,那么你必须覆盖服务器上的那几个以Test开头的class类,如果只覆盖了Test.class则有可能你新修改的代码部分将不会在服务器上起作用,这是一般初学者容易犯的问题,因为当初我也犯过同样的错误。  所以我这里需要加载的就是想把那些子类也通过byte[] classData = loadClassData(namefile);也加载进来
      

  16.   

    不用跟我举例子,你对内部类,bytecode还有classloader的理解有误
    我跟你举个例子,我前几个月,刚刚写过一个基于httpclient的classloader,也涉及到版本更新。你的问题完全思路错了。热部署做的不是也不可能是现有classloader重新去加载,而是销毁一个classloader,重新用个性的classloader
      

  17.   

    它跟普通的类不一样,举个例子假如              如果一个java文件编译后生成多个class文件,如果你把其它的两个子类删掉,则这个class就报错,但是如果跟你举个例子,假如项目已经上线一段时间了,客户提出需求后你只修改了一个名字叫Test.java的文件,如果这个Test.java编译后只有一个class文件,那么你只覆盖服务器上的Test.class一个文件即可,假如Test.java这个文件编译好后生成多个以Test开头的class文件,那么你必须覆盖服务器上的那几个以Test开头的class类,如果只覆盖了Test.class则有可能你新修改的代码部分将不会在服务器上起作用,这是一般初学者容易犯的问题,因为当初我也犯过同样的错误。  所以我这里需要加载的就是想把那些子类也通过byte[] classData = loadClassData(namefile);也加载进来如果一个类重新编译后差生了多个类,那么你必然需要将这些所有的类同时提交到服务器上,有什么问题么? 加设你新的类编译生成了C.class, C$1.class, C$2.class, 那么你必须同时将这些类提交到服务器上,如果C.class 用到了内部类C$1.class,必然会通过类加载器寻找,然后就可以从数据库中拿到,这个逻辑有什么问题吗