Java: How to load Class stored as byte[] into the JVM?

[亡魂溺海] 提交于 2019-11-27 12:06:53

I'm actually using something like this right now in a test to give a set of Class definitions as byte[] to a ClassLoader:

  public static class ByteClassLoader extends URLClassLoader {
    private final Map<String, byte[]> extraClassDefs;

    public ByteClassLoader(URL[] urls, ClassLoader parent, Map<String, byte[]> extraClassDefs) {
      super(urls, parent);
      this.extraClassDefs = new HashMap<String, byte[]>(extraClassDefs);
    }

    @Override
    protected Class<?> findClass(final String name) throws ClassNotFoundException {
      byte[] classBytes = this.extraClassDefs.remove(name);
      if (classBytes != null) {
        return defineClass(name, classBytes, 0, classBytes.length); 
      }
      return super.findClass(name);
    }

  }

Use the defineClass(String, byte[], int, int) method from ClassLoader

Extend ClassLoader and then implement the necessary call to obtain your byte[] inside the method defineClass(). Conversely you can do this in findClass(). You'll thus load this ClassLoader at the beginning or employ it when you need class definitions via your array.

public class ByteArrayClassLoader extends ClassLoader {

    public Class findClass(String name) {
        byte[] ba = /* go obtain your byte array by the name */;

        return defineClass(name,ba,0,ba.length);
    }

}

Okay, so here's what I did:

public class AgentClassLoader extends ClassLoader
{
  public void loadThisClass(ClassByte classByte_)
  {
    resolveClass(defineClass(classByte_.getName(),
                             classByte_.getBytes(),
                             0,
                             classByte_.getBytes().length));
  }
}

I hope that loads the class into JVM? If this really works, why didn't Java implementator make both defineClass and resolveClass public methods? I really wonder what they were thinking. Anyone can enlighten me?

Just for completeness, here's ClassByte

import java.io.Serializable;

public class ClassByte implements Serializable
{
  private String name;
  private byte[] bytes;

  ClassByte(String name_, byte[] bytes_)
  {
    name  = name_;
    bytes = bytes_;
  }

  public String getName()
  {
    return name;
  }

  public byte[] getBytes()
  {
    return bytes;
  }
}

The answer of Alex is correct but if you have inheritance relationship between classes you need to make sure you load the parent class first. Otherwise the class loader won't be able to define it.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!