Skip to content

Commit

Permalink
* exewrap 1.6.2
Browse files Browse the repository at this point in the history
カスタムクラスローダー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を見つけられるようになります。

git-svn-id: http://svn.osdn.net/svnroot/exewrap/exewrap/trunk/exewrap@90 d83a06de-854e-4732-85b7-fdf7162022b6
  • Loading branch information
hirukawa_ryo committed Jul 12, 2020
1 parent 629add4 commit 1d9d88c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/include/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
51 changes: 45 additions & 6 deletions src/java/Loader.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
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;
Expand All @@ -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<String, byte[]> classes = new HashMap<String, byte[]>();
Expand All @@ -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 + "!/");
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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<String> paths = new HashSet<String>();
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 {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down
15 changes: 10 additions & 5 deletions src/jvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down
8 changes: 4 additions & 4 deletions src/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/resources/exewrap.rc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
}
}
Expand Down

0 comments on commit 1d9d88c

Please sign in to comment.