Since you said “at least list all of the files that exist inside the JAR”, let’s begin with that rather easy task.
Suppose, you have your JarFile in a byte array, byte[] buffer
:
try(JarInputStream is=new JarInputStream(new ByteArrayInputStream(buffer))) {
for(;;) {
JarEntry nextEntry = is.getNextJarEntry();
if(nextEntry==null) break;
System.out.println(nextEntry);
}
}
Loading classes from such a representation doesn’t work out-of-the-box because the standard ClassLoader
implementations rely on the JarFile
implementation which relies on a physical file rather than an abstraction.
So unless you simply write the buffer into a temporary file, it boils down to implement your own ClassLoader
. Since the JRE supports only stream access as shown above, you will have to scan linearly to find a requested resource/class or iterate once and store the entries into a Map
.
One alternative to implementing a ClassLoader
is to implement a custom URL
handler to use together with a URLClassLoader
which reduces the task to the lookup as described above:
final Map<String,byte[]> map=new HashMap<>();
try(JarInputStream is=new JarInputStream(new ByteArrayInputStream(buffer))) {
for(;;) {
JarEntry nextEntry = is.getNextJarEntry();
if(nextEntry==null) break;
final int est=(int)nextEntry.getSize();
byte[] data=new byte[est>0? est: 1024];
int real=0;
for(int r=is.read(data); r>0; r=is.read(data, real, data.length-real))
if(data.length==(real+=r)) data=Arrays.copyOf(data, data.length*2);
if(real!=data.length) data=Arrays.copyOf(data, real);
map.put("/"+nextEntry.getName(), data);
}
}
URL u=new URL("x-buffer", null, -1, "/", new URLStreamHandler() {
protected URLConnection openConnection(URL u) throws IOException {
final byte[] data = map.get(u.getFile());
if(data==null) throw new FileNotFoundException(u.getFile());
return new URLConnection(u) {
public void connect() throws IOException {}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
};
}
});
try(URLClassLoader cl=new URLClassLoader(new URL[]{u})) {
cl.loadClass( ? a class from your JarFile buffer ?);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…