GT-3146: Preventing Ghidra from launching with 32-bit Java (fixes #882).

This commit is contained in:
Ryan Kurtz 2019-09-12 09:40:36 -04:00
parent d9da0f0b66
commit 0a3574d0c0
6 changed files with 93 additions and 37 deletions

View File

@ -6,7 +6,7 @@ The following is a list of dependencies, in no particular order.
This guide includes instructions for obtaining many of these at the relevant step(s).
You may not need all of these, depending on which portions you are building or developing.
* Java JDK 11 - Free long term support (LTS) versions of JDK 11 are provided by:
* Java JDK 11 (64-bit) - Free long term support (LTS) versions of JDK 11 are provided by:
- AdoptOpenJDK
- https://adoptopenjdk.net/releases.html?variant=openjdk11&jvmVariant=hotspot
- Amazon Corretto

View File

@ -224,10 +224,11 @@ public class LaunchSupport {
javaRange = min + "-" + max;
}
System.out.println("*******************************************************");
System.out.println("******************************************************************");
System.out.println(
javaName + " " + javaRange + " could not be found and must be manually chosen!");
System.out.println("*******************************************************");
javaName + " " + javaRange + " (" + javaConfig.getSupportedArchitecture() +
"-bit) could not be found and must be manually chosen!");
System.out.println("******************************************************************");
File javaHomeDir = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
@ -259,7 +260,7 @@ public class LaunchSupport {
}
System.out.println(
"Java version " + javaVersion + " is outside of supported range: [" +
javaRange + "]");
javaRange + " " + javaConfig.getSupportedArchitecture() + "-bit]");
}
catch (FileNotFoundException e) {
System.out.println(

View File

@ -84,6 +84,16 @@ public class JavaConfig {
return maxSupportedJava;
}
/**
* Gets the Java configuration's supported Java architecture. All supported Java
* configurations must have an architecture of <code>64</code>.
*
* @return The Java configuration's supported Java architecture (64).
*/
public int getSupportedArchitecture() {
return 64;
}
/**
* Gets the Java configuration's compiler compliance level that was used to build the
* associated installation.
@ -161,6 +171,10 @@ public class JavaConfig {
* @return True if the given Java version is supported by this Java launch configuration.
*/
public boolean isJavaVersionSupported(JavaVersion javaVersion) {
if (javaVersion.getArchitecture() != getSupportedArchitecture()) {
return false;
}
int major = javaVersion.getMajor();
return major >= minSupportedJava &&
(maxSupportedJava == 0 || major <= maxSupportedJava);
@ -229,29 +243,34 @@ public class JavaConfig {
*/
private JavaVersion runAndGetJavaVersion(File javaExecutable)
throws ParseException, IOException {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(new String[] { javaExecutable.getAbsolutePath(), "-version" });
String version = "";
String arch = "";
Process proc = Runtime.getRuntime().exec(new String[] { javaExecutable.getAbsolutePath(),
"-XshowSettings:properties", "-version" });
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
while ((version.isEmpty() || arch.isEmpty()) && (line = reader.readLine()) != null) {
line = line.trim();
// If the _JAVA_OPTIONS or JAVA_TOOL_OPTIONS environment variables are set, STDERR
// will start with "Picked up..." lines that need to be ignored so we can get to the
// java version line.
if (line.startsWith("Picked up")) {
continue;
}
String[] parts = line.split("\\s");
if (parts.length < 3) {
throw new ParseException("Failed to parse version: " + line, 0);
String searchString = "java.version = ";
if (line.startsWith(searchString)) {
version = line.substring(searchString.length());
}
searchString = "sun.arch.data.model = ";
if (line.startsWith(searchString)) {
arch = line.substring(searchString.length());
}
return new JavaVersion(parts[2]);
}
}
if (version.isEmpty()) {
throw new ParseException("Failed to find Java version", 0);
}
if (arch.isEmpty()) {
throw new ParseException("Failed to find Java architecture", 0);
}
return new JavaVersion(version, arch);
}
/**

View File

@ -19,22 +19,29 @@ import java.text.ParseException;
/**
* Class to more conveniently represent a Java version string.
* <p>
* Note: this class has a natural ordering that is inconsistent with equals
* (the <code>architecture</code> part of the version is disregarded in the
* {@link #compareTo(JavaVersion)} method).
*/
public class JavaVersion implements Comparable<JavaVersion> {
private int major;
private int minor;
private int patch;
private int arch;
/**
* Creates a new {@link JavaVersion} object from the given version string.
*
* @param version A version string.
* @throws ParseException if the version string failed to parse. The exception's
* message has more detailed information about why it failed.
* @param architecture An architecture string (32 or 64).
* @throws ParseException if the version or architecture string failed to parse.
* The exception's message has more detailed information about why it failed.
*/
public JavaVersion(String version) throws ParseException {
parse(version);
public JavaVersion(String version, String architecture) throws ParseException {
parseVersion(version);
parseArchitecture(architecture);
}
/**
@ -64,12 +71,21 @@ public class JavaVersion implements Comparable<JavaVersion> {
return patch;
}
/**
* Gets the architecture.
*
* @return The architecture.
*/
public int getArchitecture() {
return arch;
}
@Override
public String toString() {
if (major < 9) {
return String.format("1.%d.%d_%d", major, minor, patch);
return String.format("1.%d.%d_%d (%d-bit)", major, minor, patch, arch);
}
return String.format("%d.%d.%d", major, minor, patch);
return String.format("%d.%d.%d (%d-bit)", major, minor, patch, arch);
}
@Override
@ -102,6 +118,7 @@ public class JavaVersion implements Comparable<JavaVersion> {
result = prime * result + major;
result = prime * result + minor;
result = prime * result + patch;
result = prime * result + arch;
return result;
}
@ -126,6 +143,9 @@ public class JavaVersion implements Comparable<JavaVersion> {
if (patch != other.patch) {
return false;
}
if (arch != other.arch) {
return false;
}
return true;
}
@ -136,7 +156,7 @@ public class JavaVersion implements Comparable<JavaVersion> {
* @throws ParseException if the version string failed to parse. The exception's message
* has more detailed information about why it failed.
*/
private void parse(String version) throws ParseException {
private void parseVersion(String version) throws ParseException {
if (version == null) {
throw new ParseException("Version is null", 0);
}
@ -155,26 +175,26 @@ public class JavaVersion implements Comparable<JavaVersion> {
}
String[] versionParts = version.split("[._]");
int firstValue = parse(versionParts[0], "first value");
int firstValue = parseVersionPart(versionParts[0], "first value");
if (firstValue == 1) {
// Follows the Java 8 and earlier format of 1.major.minor_patch
if (versionParts.length > 1) {
major = parse(versionParts[1], "major");
major = parseVersionPart(versionParts[1], "major");
if (versionParts.length > 2) {
minor = parse(versionParts[2], "minor");
minor = parseVersionPart(versionParts[2], "minor");
if (versionParts.length > 3) {
patch = parse(versionParts[3], "patch");
patch = parseVersionPart(versionParts[3], "patch");
}
}
}
}
else if (firstValue >= 9) {
// Follows the Java 9 and later format of major.minor.patch
major = parse(versionParts[0], "major");
major = parseVersionPart(versionParts[0], "major");
if (versionParts.length > 1) {
minor = parse(versionParts[1], "minor");
minor = parseVersionPart(versionParts[1], "minor");
if (versionParts.length > 2) {
patch = parse(versionParts[2], "patch");
patch = parseVersionPart(versionParts[2], "patch");
}
}
}
@ -192,7 +212,7 @@ public class JavaVersion implements Comparable<JavaVersion> {
* @throws ParseException if the version part string failed to parse to a valid version part
* integer.
*/
private int parse(String versionPart, String versionPartName) throws ParseException {
private int parseVersionPart(String versionPart, String versionPartName) throws ParseException {
try {
int i = Integer.parseInt(versionPart);
if (i < 0) {
@ -205,4 +225,19 @@ public class JavaVersion implements Comparable<JavaVersion> {
0);
}
}
/**
* Parses the architecture integer out of the given architecture string.
*
* @param architecture An architecture string.
* @throws ParseException if the architecture string failed to parse.
*/
private void parseArchitecture(String architecture) throws ParseException {
try {
arch = Integer.parseInt(architecture);
}
catch (NumberFormatException e) {
throw new ParseException("Failed to parse architecture: " + architecture, 0);
}
}
}

View File

@ -28,6 +28,7 @@ public class WindowsJavaFinder extends JavaFinder {
protected List<File> getJavaRootInstallDirs() {
List<File> javaRootInstallDirs = new ArrayList<>();
javaRootInstallDirs.add(new File("C:\\Program Files\\Java"));
javaRootInstallDirs.add(new File("C:\\Program Files\\Amazon Corretto"));
return javaRootInstallDirs;
}

View File

@ -81,7 +81,7 @@ Ghidra team if you have a specific need.</p></blockquote>
</ul>
<h3>Software</h3>
<ul>
<li>Java 11 Runtime and Development Kit (JDK) (see <a href="#JavaNotes">Java Notes</a>)</li>
<li>Java 11 64-bit Runtime and Development Kit (JDK) (see <a href="#JavaNotes">Java Notes</a>)</li>
<ul>
<li>Free long term support (LTS) versions of JDK 11 are provided by:</li>
<ul>
@ -406,7 +406,7 @@ be installed in a pre-existing Eclipse installation.</p>
<p>(<a href="#top">Back to Top</a>)</p>
<h2><a name="Upgrading"></a>Upgrade Instructions</h2>
<h3><a name="GeneralUpgrade"</a>General Upgrade Instructions</h3>
<h3><a name="GeneralUpgrade"></a>General Upgrade Instructions</h3>
<ol>
<li>
<b><font color="red">!!!Important!!!</font> BACKUP YOUR OLD PROJECTS FIRST!!<font color="red">
@ -436,7 +436,7 @@ be installed in a pre-existing Eclipse installation.</p>
</li>
</ol>
<h3><a name="ServerUpgrade"</a>Server Upgrade Instructions</h3>
<h3><a name="ServerUpgrade"></a>Server Upgrade Instructions</h3>
<ul>
<li>
Please refer to the<i>&lt;GhidraInstallDir&gt;</i>/server/svrREADME.html file for details on