• R/O
  • SSH
  • HTTPS

exewrap: Commit


Commit MetaInfo

Revision90 (tree)
Time2020-07-12 20:16:23
Authorhirukawa_ryo

Log Message

* exewrap 1.6.2
カスタムクラスローダーLoaderがURLClassLoaderを継承するように変更し、Loaderが外部ライブラリ(JAR)からのクラスロードも担当するように変更しました。
従来はLoaderはEXE内リソースからのクラスロードのみを担当し、外部ライブラリ(JAR)からのクラスロードは親クラスローダー(AppClassLoader)に任せていました。
クラスローダーがLoaderとAppClassLoaderの2つに分かれていると意図しない動作をするケースがあるための対処です。

たとえば、logbackはlogbackのクラスをロードしたクラスローダーからしか設定ファイルlogback.xmlリソースを検索しません。
このようなケースでlogbackのクラスがAppClassLoaderの担当する外部ライブラリ(JAR)からロードされ、設定ファイルlogback.xmlがLoaderの担当するEXE内リソースに存在すると
logbackのクラスが設定ファイルlogback.xmlを見つけることができませんでした。
今回の対処により外部ライブラリ(JAR)からのlogbackクラスもLoaderによってロードされるようになり、Loader担当のEXE内リソースlogback.xmlを見つけられるようになります。

Change Summary

Incremental Difference

--- exewrap/trunk/exewrap/src/include/jvm.h (revision 89)
+++ exewrap/trunk/exewrap/src/include/jvm.h (revision 90)
@@ -19,6 +19,7 @@
1919 extern JNIEnv* attach_java_vm(void);
2020 extern jint detach_java_vm(void);
2121 extern BOOL set_application_properties(SYSTEMTIME* startup);
22+extern wchar_t* get_classpath(void);
2223 extern void get_java_runtime_version(const wchar_t* version_string, DWORD* major, DWORD* minor, DWORD* build, DWORD* revision);
2324 extern wchar_t* get_java_version_string(DWORD major, DWORD minor, DWORD build, DWORD revision);
2425 extern wchar_t* get_module_version(wchar_t* buf, size_t size);
--- exewrap/trunk/exewrap/src/java/Loader.java (revision 89)
+++ exewrap/trunk/exewrap/src/java/Loader.java (revision 90)
@@ -1,4 +1,5 @@
11 import java.io.ByteArrayOutputStream;
2+import java.io.File;
23 import java.io.FileDescriptor;
34 import java.io.FileOutputStream;
45 import java.io.IOException;
@@ -6,6 +7,7 @@
67 import java.io.UnsupportedEncodingException;
78 import java.net.MalformedURLException;
89 import java.net.URL;
10+import java.net.URLClassLoader;
911 import java.net.URLEncoder;
1012 import java.net.URLStreamHandler;
1113 import java.net.URLStreamHandlerFactory;
@@ -15,15 +17,17 @@
1517 import java.security.ProtectionDomain;
1618 import java.security.cert.Certificate;
1719 import java.util.HashMap;
20+import java.util.HashSet;
1821 import java.util.LinkedList;
1922 import java.util.Map;
2023 import java.util.Queue;
24+import java.util.Set;
2125 import java.util.jar.JarEntry;
2226 import java.util.jar.JarInputStream;
2327 import java.util.jar.Manifest;
2428 import java.util.jar.Attributes.Name;
2529
26-public class Loader extends ClassLoader {
30+public class Loader extends URLClassLoader {
2731
2832 private static String CONTEXT_PATH;
2933 private static Map<String, byte[]> classes = new HashMap<String, byte[]>();
@@ -41,7 +45,7 @@
4145 private static URL context;
4246 private static URLStreamHandler handler;
4347
44- public static Class<?> initialize(JarInputStream[] jars, URLStreamHandlerFactory factory, String utilities, String mainClassName, int consoleCodePage) throws MalformedURLException, ClassNotFoundException {
48+ public static Class<?> initialize(JarInputStream[] jars, URLStreamHandlerFactory factory, String utilities, String classPath, String mainClassName, int consoleCodePage) throws MalformedURLException, ClassNotFoundException {
4549 URL.setURLStreamHandlerFactory(factory);
4650 handler = factory.createURLStreamHandler("exewrap");
4751 context = new URL("exewrap:" + CONTEXT_PATH + "!/");
@@ -69,7 +73,7 @@
6973 jar = inputs.poll();
7074
7175 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
72-
76+
7377 if(utilities != null) {
7478 if(System.getProperty("exewrap.console.encoding") == null)
7579 {
@@ -102,7 +106,31 @@
102106 Class.forName("exewrap.util.EventLogHandler", true, systemClassLoader);
103107 }
104108 }
105-
109+
110+ if(systemClassLoader instanceof Loader) {
111+ Loader loader = (Loader)systemClassLoader;
112+
113+ try {
114+ // カレントディレクトリをCLASS_PATHに追加します。
115+ classPath = new File(".").getCanonicalPath() + ";" + classPath;
116+ } catch(Exception ignore) {}
117+
118+ Set<String> paths = new HashSet<String>();
119+ for(String path : classPath.split(";")) {
120+ try {
121+ if(path.length() > 0) {
122+ File file = new File(path).getCanonicalFile();
123+ String s = file.toString().toLowerCase();
124+ if(!paths.contains(s)) {
125+ URL url = file.toURI().toURL();
126+ loader.addURL(url);
127+ paths.add(s);
128+ }
129+ }
130+ } catch(Exception ignore) {}
131+ }
132+ }
133+
106134 if(mainClassName != null) {
107135 return Class.forName(mainClassName, true, systemClassLoader);
108136 } else {
@@ -114,7 +142,7 @@
114142 private ProtectionDomain protectionDomain;
115143
116144 public Loader(ClassLoader parent) throws MalformedURLException {
117- super(parent);
145+ super(new URL[0], parent);
118146
119147 String path = System.getProperty("java.application.path");
120148 if(path == null) {
@@ -140,6 +168,11 @@
140168 }
141169
142170 protected Class<?> findClass(String name) throws ClassNotFoundException {
171+ // 外部ライブラリ(JAR)からクラスを探します。見つからなければEXEリソースからクラスを探します。
172+ try {
173+ return super.findClass(name);
174+ } catch(ClassNotFoundException ignore) {}
175+
143176 String entryName = name.replace('.', '/').concat(".class");
144177 byte[] bytes = classes.remove(entryName);
145178 if(bytes == null) {
@@ -169,7 +202,13 @@
169202 return defineClass(name, bytes, 0, bytes.length, protectionDomain);
170203 }
171204
172- protected URL findResource(String name) {
205+ public URL findResource(String name) {
206+ // 外部ライブラリ(JAR)からリソースを探します。見つからなければEXEリソースからリソースを探します。
207+ URL url = super.findResource(name);
208+ if(url != null) {
209+ return url;
210+ }
211+
173212 byte[] bytes = resources.get(name);
174213 if(bytes == null) {
175214 try {
--- exewrap/trunk/exewrap/src/jvm.c (revision 89)
+++ exewrap/trunk/exewrap/src/jvm.c (revision 90)
@@ -17,6 +17,7 @@
1717 JNIEnv* attach_java_vm(void);
1818 jint detach_java_vm(void);
1919 BOOL set_application_properties(SYSTEMTIME* startup);
20+wchar_t* get_class_path(void);
2021 void get_java_runtime_version(const wchar_t* version_string, DWORD* major, DWORD* minor, DWORD* build, DWORD* revision);
2122 wchar_t* get_java_version_string(DWORD major, DWORD minor, DWORD build, DWORD revision);
2223 wchar_t* get_module_version(wchar_t* buf, size_t size);
@@ -149,12 +150,12 @@
149150 goto EXIT;
150151 }
151152
152- if(classpath != NULL)
153+ if(GetModuleFileName(NULL, wchar_buf, BUFFER_SIZE) != 0)
153154 {
154155 char* str;
155156 size_t len;
156157
157- str = to_platform_encoding(classpath);
158+ str = to_platform_encoding(wchar_buf);
158159 strcpy_s(char_buf, BUFFER_SIZE * 2, "-Djava.class.path=");
159160 strcat_s(char_buf, BUFFER_SIZE * 2, str);
160161 free(str);
@@ -836,6 +837,12 @@
836837 }
837838
838839
840+wchar_t* get_classpath()
841+{
842+ return classpath;
843+}
844+
845+
839846 BOOL initialize_path(const wchar_t* relative_classpath, const wchar_t* relative_extdirs, BOOL use_server_vm, BOOL use_side_by_side_jre)
840847 {
841848 wchar_t* module_path = NULL;
@@ -1360,8 +1367,7 @@
13601367
13611368
13621369 GetModuleFileName(NULL, buffer, BUFFER_SIZE);
1363- wcscpy_s(classpath, BUFFER_SIZE, buffer);
1364- wcscat_s(classpath, BUFFER_SIZE, L";");
1370+ wcscpy_s(classpath, BUFFER_SIZE, L"");
13651371
13661372 wcscpy_s(libpath, BUFFER_SIZE, L".;");
13671373 wcscat_s(libpath, BUFFER_SIZE, jvmpath);
@@ -1390,7 +1396,6 @@
13901396 p = NULL;
13911397 }
13921398 }
1393- wcscat_s(classpath, BUFFER_SIZE, L".");
13941399
13951400 if(relative_extdirs != NULL)
13961401 {
--- exewrap/trunk/exewrap/src/loader.c (revision 89)
+++ exewrap/trunk/exewrap/src/loader.c (revision 90)
@@ -179,11 +179,11 @@
179179 swprintf_s(result->msg, LOAD_RESULT_MAX_MESSAGE_LENGTH, _(MSG_ID_ERR_GET_FIELD), L"Loader.resources");
180180 goto EXIT;
181181 }
182- Loader_initialize = (*env)->GetStaticMethodID(env, Loader, "initialize", "([Ljava/util/jar/JarInputStream;Ljava/net/URLStreamHandlerFactory;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Class;");
182+ 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;");
183183 if(Loader_initialize == NULL)
184184 {
185185 result->msg_id = MSG_ID_ERR_GET_METHOD;
186- 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)");
186+ 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)");
187187 goto EXIT;
188188 }
189189
@@ -400,11 +400,11 @@
400400 }
401401 (*env)->SetObjectArrayElement(env, jars, 1, jarInputStream);
402402 }
403-
403+
404404 // call Loader.initialize
405405 main_class = from_utf8((char*)get_resource(L"MAIN_CLASS", NULL)); // MAIN_CLASSは定義されていない場合は main_class = NULL のまま処理を進めます。
406406 console_code_page = GetConsoleOutputCP();
407- MainClass = (*env)->CallStaticObjectMethod(env, Loader, Loader_initialize, jars, urlStreamHandlerFactory, to_jstring(env, utilities), to_jstring(env, main_class), console_code_page);
407+ 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);
408408 if(MainClass == NULL)
409409 {
410410 result->msg_id = MSG_ID_ERR_LOAD_MAIN_CLASS;
Show on old repository browser