mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8318812: LauncherHelper.checkAndLoadMain closes jar file that's about to be re-opened
Reviewed-by: alanb, jpai, coffeys
This commit is contained in:
parent
69a11c7f7e
commit
0d285312a9
2 changed files with 86 additions and 70 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -590,73 +590,69 @@ public final class LauncherHelper {
|
|||
ostream = ps;
|
||||
}
|
||||
|
||||
static String getMainClassFromJar(String jarname) {
|
||||
String mainValue;
|
||||
try (JarFile jarFile = new JarFile(jarname)) {
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
if (manifest == null) {
|
||||
abort(null, "java.launcher.jar.error2", jarname);
|
||||
}
|
||||
Attributes mainAttrs = manifest.getMainAttributes();
|
||||
if (mainAttrs == null) {
|
||||
abort(null, "java.launcher.jar.error3", jarname);
|
||||
}
|
||||
|
||||
// Main-Class
|
||||
mainValue = mainAttrs.getValue(MAIN_CLASS);
|
||||
if (mainValue == null) {
|
||||
abort(null, "java.launcher.jar.error3", jarname);
|
||||
}
|
||||
|
||||
// Launcher-Agent-Class (only check for this when Main-Class present)
|
||||
String agentClass = mainAttrs.getValue(LAUNCHER_AGENT_CLASS);
|
||||
if (agentClass != null) {
|
||||
ModuleLayer.boot().findModule("java.instrument").ifPresent(m -> {
|
||||
try {
|
||||
String cn = "sun.instrument.InstrumentationImpl";
|
||||
Class<?> clazz = Class.forName(cn, false, null);
|
||||
Method loadAgent = clazz.getMethod("loadAgent", String.class);
|
||||
loadAgent.invoke(null, jarname);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof InvocationTargetException) e = e.getCause();
|
||||
abort(e, "java.launcher.jar.error4", jarname);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add-Exports and Add-Opens
|
||||
String exports = mainAttrs.getValue(ADD_EXPORTS);
|
||||
if (exports != null) {
|
||||
addExportsOrOpens(exports, false);
|
||||
}
|
||||
String opens = mainAttrs.getValue(ADD_OPENS);
|
||||
if (opens != null) {
|
||||
addExportsOrOpens(opens, true);
|
||||
}
|
||||
String enableNativeAccess = mainAttrs.getValue(ENABLE_NATIVE_ACCESS);
|
||||
if (enableNativeAccess != null) {
|
||||
if (!enableNativeAccess.equals("ALL-UNNAMED")) {
|
||||
abort(null, "java.launcher.jar.error.illegal.ena.value", enableNativeAccess);
|
||||
}
|
||||
Modules.addEnableNativeAccessToAllUnnamed();
|
||||
}
|
||||
|
||||
/*
|
||||
* Hand off to FXHelper if it detects a JavaFX application
|
||||
* This must be done after ensuring a Main-Class entry
|
||||
* exists to enforce compliance with the jar specification
|
||||
*/
|
||||
if (mainAttrs.containsKey(
|
||||
new Attributes.Name(JAVAFX_APPLICATION_MARKER))) {
|
||||
FXHelper.setFXLaunchParameters(jarname, LM_JAR);
|
||||
return FXHelper.class.getName();
|
||||
}
|
||||
|
||||
return mainValue.trim();
|
||||
} catch (IOException ioe) {
|
||||
abort(ioe, "java.launcher.jar.error1", jarname);
|
||||
private static String getMainClassFromJar(JarFile jarFile) throws IOException {
|
||||
String jarname = jarFile.getName();
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
if (manifest == null) {
|
||||
abort(null, "java.launcher.jar.error2", jarname);
|
||||
}
|
||||
return null;
|
||||
|
||||
Attributes mainAttrs = manifest.getMainAttributes();
|
||||
if (mainAttrs == null) {
|
||||
abort(null, "java.launcher.jar.error3", jarname);
|
||||
}
|
||||
|
||||
// Main-Class
|
||||
String mainValue = mainAttrs.getValue(MAIN_CLASS);
|
||||
if (mainValue == null) {
|
||||
abort(null, "java.launcher.jar.error3", jarname);
|
||||
}
|
||||
|
||||
// Launcher-Agent-Class (only check for this when Main-Class present)
|
||||
String agentClass = mainAttrs.getValue(LAUNCHER_AGENT_CLASS);
|
||||
if (agentClass != null) {
|
||||
ModuleLayer.boot().findModule("java.instrument").ifPresent(m -> {
|
||||
try {
|
||||
String cn = "sun.instrument.InstrumentationImpl";
|
||||
Class<?> clazz = Class.forName(cn, false, null);
|
||||
Method loadAgent = clazz.getMethod("loadAgent", String.class);
|
||||
loadAgent.invoke(null, jarname);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof InvocationTargetException) e = e.getCause();
|
||||
abort(e, "java.launcher.jar.error4", jarname);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add-Exports and Add-Opens
|
||||
String exports = mainAttrs.getValue(ADD_EXPORTS);
|
||||
if (exports != null) {
|
||||
addExportsOrOpens(exports, false);
|
||||
}
|
||||
String opens = mainAttrs.getValue(ADD_OPENS);
|
||||
if (opens != null) {
|
||||
addExportsOrOpens(opens, true);
|
||||
}
|
||||
String enableNativeAccess = mainAttrs.getValue(ENABLE_NATIVE_ACCESS);
|
||||
if (enableNativeAccess != null) {
|
||||
if (!enableNativeAccess.equals("ALL-UNNAMED")) {
|
||||
abort(null, "java.launcher.jar.error.illegal.ena.value", enableNativeAccess);
|
||||
}
|
||||
Modules.addEnableNativeAccessToAllUnnamed();
|
||||
}
|
||||
|
||||
/*
|
||||
* Hand off to FXHelper if it detects a JavaFX application
|
||||
* This must be done after ensuring a Main-Class entry
|
||||
* exists to enforce compliance with the jar specification
|
||||
*/
|
||||
if (mainAttrs.containsKey(
|
||||
new Attributes.Name(JAVAFX_APPLICATION_MARKER))) {
|
||||
FXHelper.setFXLaunchParameters(jarname, LM_JAR);
|
||||
return FXHelper.class.getName();
|
||||
}
|
||||
|
||||
return mainValue.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -819,13 +815,23 @@ public final class LauncherHelper {
|
|||
*/
|
||||
private static Class<?> loadMainClass(int mode, String what) {
|
||||
// get the class name
|
||||
String cn;
|
||||
String cn = null;
|
||||
// In LM_JAR mode, keep the underlying file open to retain it in
|
||||
// the JarFile/ZipFile cache. This will avoid needing to re-parse
|
||||
// the central directory when the file is opened on the class path,
|
||||
// triggered by Class.forName below.
|
||||
JarFile jarFile = null;
|
||||
switch (mode) {
|
||||
case LM_CLASS:
|
||||
cn = what;
|
||||
break;
|
||||
case LM_JAR:
|
||||
cn = getMainClassFromJar(what);
|
||||
try {
|
||||
jarFile = new JarFile(what);
|
||||
cn = getMainClassFromJar(jarFile);
|
||||
} catch (IOException ioe) {
|
||||
abort(ioe, "java.launcher.jar.error1", what);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// should never happen
|
||||
|
@ -861,6 +867,14 @@ public final class LauncherHelper {
|
|||
} catch (LinkageError le) {
|
||||
abort(le, "java.launcher.cls.error4", cn,
|
||||
le.getClass().getName() + ": " + le.getLocalizedMessage());
|
||||
} finally {
|
||||
if (jarFile != null) {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (IOException ioe) {
|
||||
abort(ioe, "java.launcher.jar.error5", what);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -261,6 +261,8 @@ java.launcher.jar.error1=\
|
|||
java.launcher.jar.error2=manifest not found in {0}
|
||||
java.launcher.jar.error3=no main manifest attribute, in {0}
|
||||
java.launcher.jar.error4=error loading java agent in {0}
|
||||
java.launcher.jar.error5=\
|
||||
Error: An unexpected error occurred while trying to close file {0}
|
||||
java.launcher.jar.error.illegal.ena.value=\
|
||||
Error: illegal value \"{0}\" for Enable-Native-Access manifest attribute. Only 'ALL-UNNAMED' is allowed
|
||||
java.launcher.init.error=initialization error
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue