diff --git a/src/include/jvm.h b/src/include/jvm.h index b88d176..27c0777 100644 --- a/src/include/jvm.h +++ b/src/include/jvm.h @@ -19,6 +19,7 @@ extern jint destroy_java_vm(void); extern JNIEnv* attach_java_vm(void); extern jint detach_java_vm(void); extern BOOL set_application_properties(SYSTEMTIME* startup); +extern wchar_t* get_classpath(void); extern void get_java_runtime_version(const wchar_t* version_string, DWORD* major, DWORD* minor, DWORD* build, DWORD* revision); extern wchar_t* get_java_version_string(DWORD major, DWORD minor, DWORD build, DWORD revision); extern wchar_t* get_module_version(wchar_t* buf, size_t size); diff --git a/src/java/Loader.java b/src/java/Loader.java index 5046ad3..e678489 100644 --- a/src/java/Loader.java +++ b/src/java/Loader.java @@ -1,4 +1,5 @@ import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; @@ -6,6 +7,7 @@ import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLClassLoader; import java.net.URLEncoder; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; @@ -15,15 +17,17 @@ import java.security.ProtectionDomain; import java.security.cert.Certificate; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Queue; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.jar.Manifest; import java.util.jar.Attributes.Name; -public class Loader extends ClassLoader { +public class Loader extends URLClassLoader { private static String CONTEXT_PATH; private static Map classes = new HashMap(); @@ -41,7 +45,7 @@ public class Loader extends ClassLoader { private static URL context; private static URLStreamHandler handler; - public static Class initialize(JarInputStream[] jars, URLStreamHandlerFactory factory, String utilities, String mainClassName, int consoleCodePage) throws MalformedURLException, ClassNotFoundException { + public static Class initialize(JarInputStream[] jars, URLStreamHandlerFactory factory, String utilities, String classPath, String mainClassName, int consoleCodePage) throws MalformedURLException, ClassNotFoundException { URL.setURLStreamHandlerFactory(factory); handler = factory.createURLStreamHandler("exewrap"); context = new URL("exewrap:" + CONTEXT_PATH + "!/"); @@ -69,7 +73,7 @@ public static Class initialize(JarInputStream[] jars, URLStreamHandlerFactory jar = inputs.poll(); ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); - + if(utilities != null) { if(System.getProperty("exewrap.console.encoding") == null) { @@ -102,7 +106,31 @@ public static Class initialize(JarInputStream[] jars, URLStreamHandlerFactory Class.forName("exewrap.util.EventLogHandler", true, systemClassLoader); } } - + + if(systemClassLoader instanceof Loader) { + Loader loader = (Loader)systemClassLoader; + + try { + // カレントディレクトリをCLASS_PATHに追加します。 + classPath = new File(".").getCanonicalPath() + ";" + classPath; + } catch(Exception ignore) {} + + Set paths = new HashSet(); + for(String path : classPath.split(";")) { + try { + if(path.length() > 0) { + File file = new File(path).getCanonicalFile(); + String s = file.toString().toLowerCase(); + if(!paths.contains(s)) { + URL url = file.toURI().toURL(); + loader.addURL(url); + paths.add(s); + } + } + } catch(Exception ignore) {} + } + } + if(mainClassName != null) { return Class.forName(mainClassName, true, systemClassLoader); } else { @@ -114,7 +142,7 @@ public static Class initialize(JarInputStream[] jars, URLStreamHandlerFactory private ProtectionDomain protectionDomain; public Loader(ClassLoader parent) throws MalformedURLException { - super(parent); + super(new URL[0], parent); String path = System.getProperty("java.application.path"); if(path == null) { @@ -140,6 +168,11 @@ public Loader(ClassLoader parent) throws MalformedURLException { } protected Class findClass(String name) throws ClassNotFoundException { + // 外部ライブラリ(JAR)からクラスを探します。見つからなければEXEリソースからクラスを探します。 + try { + return super.findClass(name); + } catch(ClassNotFoundException ignore) {} + String entryName = name.replace('.', '/').concat(".class"); byte[] bytes = classes.remove(entryName); if(bytes == null) { @@ -169,7 +202,13 @@ protected Class findClass(String name) throws ClassNotFoundException { return defineClass(name, bytes, 0, bytes.length, protectionDomain); } - protected URL findResource(String name) { + public URL findResource(String name) { + // 外部ライブラリ(JAR)からリソースを探します。見つからなければEXEリソースからリソースを探します。 + URL url = super.findResource(name); + if(url != null) { + return url; + } + byte[] bytes = resources.get(name); if(bytes == null) { try { diff --git a/src/jvm.c b/src/jvm.c index 52fa72f..aaafa94 100644 --- a/src/jvm.c +++ b/src/jvm.c @@ -17,6 +17,7 @@ jint destroy_java_vm(void); JNIEnv* attach_java_vm(void); jint detach_java_vm(void); BOOL set_application_properties(SYSTEMTIME* startup); +wchar_t* get_class_path(void); void get_java_runtime_version(const wchar_t* version_string, DWORD* major, DWORD* minor, DWORD* build, DWORD* revision); wchar_t* get_java_version_string(DWORD major, DWORD minor, DWORD build, DWORD revision); wchar_t* get_module_version(wchar_t* buf, size_t size); @@ -149,12 +150,12 @@ JNIEnv* create_java_vm(const wchar_t* vm_args_opt, BOOL use_server_vm, BOOL use_ goto EXIT; } - if(classpath != NULL) + if(GetModuleFileName(NULL, wchar_buf, BUFFER_SIZE) != 0) { char* str; size_t len; - str = to_platform_encoding(classpath); + str = to_platform_encoding(wchar_buf); strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.class.path="); strcat_s(char_buf, BUFFER_SIZE * 2, str); free(str); @@ -836,6 +837,12 @@ BOOL set_application_properties(SYSTEMTIME* startup) } +wchar_t* get_classpath() +{ + return classpath; +} + + BOOL initialize_path(const wchar_t* relative_classpath, const wchar_t* relative_extdirs, BOOL use_server_vm, BOOL use_side_by_side_jre) { wchar_t* module_path = NULL; @@ -1360,8 +1367,7 @@ BOOL initialize_path(const wchar_t* relative_classpath, const wchar_t* relative_ GetModuleFileName(NULL, buffer, BUFFER_SIZE); - wcscpy_s(classpath, BUFFER_SIZE, buffer); - wcscat_s(classpath, BUFFER_SIZE, L";"); + wcscpy_s(classpath, BUFFER_SIZE, L""); wcscpy_s(libpath, BUFFER_SIZE, L".;"); wcscat_s(libpath, BUFFER_SIZE, jvmpath); @@ -1390,7 +1396,6 @@ BOOL initialize_path(const wchar_t* relative_classpath, const wchar_t* relative_ p = NULL; } } - wcscat_s(classpath, BUFFER_SIZE, L"."); if(relative_extdirs != NULL) { diff --git a/src/loader.c b/src/loader.c index 04a0e24..959a988 100644 --- a/src/loader.c +++ b/src/loader.c @@ -179,11 +179,11 @@ BOOL load_main_class(int argc, const wchar_t* argv[], const wchar_t* utilities, swprintf_s(result->msg, LOAD_RESULT_MAX_MESSAGE_LENGTH, _(MSG_ID_ERR_GET_FIELD), L"Loader.resources"); goto EXIT; } - Loader_initialize = (*env)->GetStaticMethodID(env, Loader, "initialize", "([Ljava/util/jar/JarInputStream;Ljava/net/URLStreamHandlerFactory;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Class;"); + Loader_initialize = (*env)->GetStaticMethodID(env, Loader, "initialize", "([Ljava/util/jar/JarInputStream;Ljava/net/URLStreamHandlerFactory;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Class;"); if(Loader_initialize == NULL) { result->msg_id = MSG_ID_ERR_GET_METHOD; - swprintf_s(result->msg, LOAD_RESULT_MAX_MESSAGE_LENGTH, _(MSG_ID_ERR_GET_METHOD), L"Loader.initialize(java.util.jar.JarInputStream[], java.net.URLStreamHandlerFactory, java.lang.String, java.lang.String, int)"); + swprintf_s(result->msg, LOAD_RESULT_MAX_MESSAGE_LENGTH, _(MSG_ID_ERR_GET_METHOD), L"Loader.initialize(java.util.jar.JarInputStream[], java.net.URLStreamHandlerFactory, java.lang.String, java.lang.String, java.lang.String, int)"); goto EXIT; } @@ -400,11 +400,11 @@ BOOL load_main_class(int argc, const wchar_t* argv[], const wchar_t* utilities, } (*env)->SetObjectArrayElement(env, jars, 1, jarInputStream); } - + // call Loader.initialize main_class = from_utf8((char*)get_resource(L"MAIN_CLASS", NULL)); // MAIN_CLASSは定義されていない場合は main_class = NULL のまま処理を進めます。 console_code_page = GetConsoleOutputCP(); - MainClass = (*env)->CallStaticObjectMethod(env, Loader, Loader_initialize, jars, urlStreamHandlerFactory, to_jstring(env, utilities), to_jstring(env, main_class), console_code_page); + MainClass = (*env)->CallStaticObjectMethod(env, Loader, Loader_initialize, jars, urlStreamHandlerFactory, to_jstring(env, utilities), to_jstring(env, get_classpath()), to_jstring(env, main_class), console_code_page); if(MainClass == NULL) { result->msg_id = MSG_ID_ERR_LOAD_MAIN_CLASS; diff --git a/src/resources/exewrap.rc b/src/resources/exewrap.rc index a7037e8..91a0299 100644 --- a/src/resources/exewrap.rc +++ b/src/resources/exewrap.rc @@ -3,7 +3,7 @@ LANGUAGE 0,0 VS_VERSION_INFO VERSIONINFO -FILEVERSION 1,6,1,0 +FILEVERSION 1,6,2,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS VS_FF_PRERELEASE FILEOS VOS_NT_WINDOWS32 @@ -16,7 +16,7 @@ FILETYPE VFT_APP VALUE "FileDescription", "Native executable java application wrapper.\0" VALUE "LegalCopyright", "(C) 2005-2020 HIRUKAWA Ryo\0" VALUE "ProductName", "exewrap\0" - VALUE "ProductVersion", "1.6.1\0" + VALUE "ProductVersion", "1.6.2\0" VALUE "OriginalFilename", "exewrap.exe\0" } }