Как в джаве можно выполнить jar файл в памяти без касания диска? Например я хочу загрузить файл с сервера и исполнить его не дропая на диск .
#include <jni.h>
int main(int argc, char** argv) {
JavaVM* jvm;
JNIEnv* env;
JavaVMInitArgs args;
args.version = JNI_VERSION_1_8;
args.nOptions = 0;
args.options = nullptr;
args.ignoreUnrecognized = true;
JNI_CreateJavaVM(&jvm, (void**)&env, &args);
jclass classLoaderClass = env->FindClass("java/lang/ClassLoader");
jmethodID defineClassMethod = env->GetMethodID(classLoaderClass, "defineClass", "(Ljava/lang/String;[BII)Ljava/lang/Class;");
jbyteArray jarBytes = env->NewByteArray(jarData.size());
env->SetByteArrayRegion(jarBytes, 0, jarData.size(), (jbyte*)jarData.data());
jclass mainClass = (jclass)env->CallObjectMethod(env->GetClassLoader(), defineClassMethod, env->NewStringUTF("имя_класса"), jarBytes, 0, jarData.size());
// получаем айди метода для выполнения
jmethodID mainMethod = env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
// оформляем арги для вызова мэйн метода
jobjectArray argsArray = env->NewObjectArray(argc, env->FindClass("java/lang/String"), nullptr);
for (int i = 0; i < argc; ++i) {
jstring arg = env->NewStringUTF(argv[i]);
env->SetObjectArrayElement(argsArray, i, arg);
}
// вызов мейн метода
env->CallStaticVoidMethod(mainClass, mainMethod, argsArray);
// чистимся
jvm->DestroyJavaVM();
return 0;
}
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
public class InMemoryJarExecutor {
private final ClassLoader parentClassLoader;
private List<String> classpathEntries = new ArrayList<>();
public InMemoryJarExecutor(ClassLoader parentClassLoader) {
this.parentClassLoader = parentClassLoader;
}
public void addClasspathEntry(String entry) {
classpathEntries.add(entry);
}
public void executeJarInMemory(String jarUrl, String[] args) throws Exception {
URL url = new URL(jarUrl);
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
inputStream.close();
byte[] jarBytes = baos.toByteArray();
File tempFile = File.createTempFile("temp", ".jar");
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(jarBytes);
fos.close();
URL[] urls = new URL[classpathEntries.size() + 1];
for (int i = 0; i < classpathEntries.size(); i++) {
urls[i] = new URL(classpathEntries.get(i));
}
urls[classpathEntries.size()] = new URL("jar:file:" + tempFile.getAbsolutePath() + "!/");
URLClassLoader cl = URLClassLoader.newInstance(urls, parentClassLoader);
JarInputStream jarInputStream = new JarInputStream(new ByteArrayInputStream(jarBytes));
Enumeration<JarEntry> entries = jarInputStream.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
Stringname = entry.getName();
if (name.endsWith(".class")) {
Class cls = cl.loadClass(name.replaceAll("/", "\\.").substring(0, name.length() - 6));
if (cls.getName().endsWith("Main")) {
Method main = cls.getMethod("main", new Class[] { String[].class });
main.invoke(null, new Object[] { args });
}
}
}
jarInputStream.close();
tempFile.delete();
}
}