[platform] recognizing additional VM options in launchers (IDEA-240526 part 2a: sources)

Making launchers concatenate platform's and user's VM options, filtering out `-XX:.*GC` from the former if present in the latter (otherwise JVM refuses to start).

GitOrigin-RevId: fd610803054190001b14c39800208ee90d88522a
This commit is contained in:
Roman Shevchenko
2021-10-15 21:37:09 +02:00
committed by intellij-monorepo-bot
parent f80a84debb
commit cbaf53602e
2 changed files with 71 additions and 69 deletions

View File

@@ -324,56 +324,62 @@ NSString *getDefaultFilePath(NSString *fileName) {
NSArray *parseVMOptions() {
NSString *vmOptionsFile = nil;
NSMutableArray *vmOptions = nil;
NSMutableArray *vmOptions = nil, *userVmOptions = nil;
// 1. $<IDE_NAME>_VM_OPTIONS
NSString *variable = [[getExecutable() uppercaseString] stringByAppendingString:@"_VM_OPTIONS"];
NSString *value = [[[NSProcessInfo processInfo] environment] objectForKey:variable];
if (value != nil) {
vmOptions = [VMOptionsReader readFile:value];
if (vmOptions != nil) {
vmOptionsFile = value;
}
}
// 2. <IDE_HOME>.vmoptions || <IDE_HOME>/bin/<bin_name>.vmoptions + <IDE_HOME>.vmoptions (Toolbox)
if (vmOptionsFile == nil) {
NSString *candidate = [NSString stringWithFormat:@"%@.vmoptions", [[NSBundle mainBundle] bundlePath]];
NSString *candidate = [[[NSProcessInfo processInfo] environment] objectForKey:variable];
NSLog(@"parseVMOptions: %@ = %@", variable, candidate);
if (candidate != nil) {
// 1. $<IDE_NAME>_VM_OPTIONS
vmOptions = [VMOptionsReader readFile:candidate];
if (vmOptions != nil) {
vmOptionsFile = candidate;
if (![vmOptions containsObject:@"-ea"]) {
candidate = getDefaultFilePath([NSString stringWithFormat:@"/bin/%@.vmoptions", getExecutable()]);
NSMutableArray *mainOptions = [VMOptionsReader readFile:candidate];
if (mainOptions != nil) {
[mainOptions addObjectsFromArray:vmOptions];
vmOptions = mainOptions;
}
}
}
else {
// 2. <IDE_HOME>/bin/<bin_name>.vmoptions ...
candidate = getDefaultFilePath([NSString stringWithFormat:@"/bin/%@.vmoptions", getExecutable()]);
NSLog(@"parseVMOptions: %@", candidate);
vmOptions = [VMOptionsReader readFile:candidate];
if (vmOptions != nil) {
vmOptionsFile = candidate;
}
// ... [+ <IDE_HOME>.vmoptions (Toolbox) || <config_directory>/<bin_name>.vmoptions]
candidate = [NSString stringWithFormat:@"%@.vmoptions", [[NSBundle mainBundle] bundlePath]];
NSLog(@"parseVMOptions: %@", candidate);
userVmOptions = [VMOptionsReader readFile:candidate];
if (userVmOptions != nil) {
vmOptionsFile = candidate;
} else {
candidate = [NSString stringWithFormat:@"%@/%@.vmoptions", getPreferencesFolderPath(), getExecutable()];
NSLog(@"parseVMOptions: %@", candidate);
userVmOptions = [VMOptionsReader readFile:candidate];
if (userVmOptions != nil) {
vmOptionsFile = candidate;
}
}
}
// 3. <config_directory>/<bin_name>.vmoptions
if (vmOptionsFile == nil) {
NSString *candidate = [NSString stringWithFormat:@"%@/%@.vmoptions", getPreferencesFolderPath(), getExecutable()];
vmOptions = [VMOptionsReader readFile:candidate];
if (vmOptions != nil) {
vmOptionsFile = candidate;
}
}
NSLog(@"parseVMOptions: platform=%d user=%d file=%@",
vmOptions == nil ? -1 : (int)[vmOptions count], userVmOptions == nil ? -1 : (int)[userVmOptions count], vmOptionsFile);
// 4. <IDE_HOME>/bin/<bin_name>.vmoptions [+ <config_directory>/user.vmoptions]
if (vmOptionsFile == nil) {
NSString *candidate = getDefaultFilePath([NSString stringWithFormat:@"/bin/%@.vmoptions", getExecutable()]);
vmOptions = [VMOptionsReader readFile:candidate];
if (vmOptions != nil) {
vmOptionsFile = candidate;
}
candidate = [NSString stringWithFormat:@"%@/user.vmoptions", getPreferencesFolderPath()];
NSMutableArray *userVmOptions = [VMOptionsReader readFile:candidate];
if (userVmOptions != nil) {
if (userVmOptions != nil) {
if (vmOptions == nil) {
vmOptions = userVmOptions;
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
BOOL (^GC_lookup)(NSString *, NSUInteger, BOOL *) = ^BOOL(NSString *s, NSUInteger i, BOOL *stop) {
return [s hasPrefix:@"-XX:+Use"] == YES && [s hasSuffix:@"GC"] == YES ? YES : NO;
};
#pragma clang diagnostic pop
if ([userVmOptions indexOfObjectPassingTest:GC_lookup] != NSNotFound) {
NSUInteger gc = [vmOptions indexOfObjectPassingTest:GC_lookup];
if (gc != NSNotFound) {
[vmOptions removeObjectAtIndex:gc];
}
}
[vmOptions addObjectsFromArray:userVmOptions];
vmOptionsFile = candidate;
}
}

View File

@@ -1,5 +1,6 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
@@ -475,7 +476,7 @@ void (JNICALL jniExitHook)(jint code) {
bool LoadVMOptions() {
char bin_vmoptions[_MAX_PATH], buffer1[_MAX_PATH], buffer2[_MAX_PATH], *vmOptionsFile = NULL;
std::vector<std::string> lines;
std::vector<std::string> lines, user_lines;
GetModuleFileNameA(NULL, bin_vmoptions, _MAX_PATH);
strcat_s(bin_vmoptions, ".vmoptions");
@@ -485,44 +486,39 @@ bool LoadVMOptions() {
if (GetEnvironmentVariableA(buffer1, buffer2, _MAX_PATH) != 0 && LoadVMOptionsFile(buffer2, lines)) {
vmOptionsFile = buffer2;
}
// 2. <IDE_HOME>.vmoptions (Toolbox) [+ <IDE_HOME>\bin\<exe_name>.vmoptions]
if (vmOptionsFile == NULL) {
else {
// 2. <IDE_HOME>\bin\<exe_name>.vmoptions ...
if (LoadVMOptionsFile(bin_vmoptions, lines)) {
vmOptionsFile = bin_vmoptions;
}
// ... [+ <IDE_HOME>.vmoptions (Toolbox) || <config_directory>\<exe_name>.vmoptions]
strcpy_s(buffer1, _MAX_PATH, bin_vmoptions);
char *ideHomeEnd = strrchr(buffer1, '\\') - 4; // "bin\"
strcpy_s(ideHomeEnd, _MAX_PATH - (ideHomeEnd - buffer1), ".vmoptions");
if (LoadVMOptionsFile(buffer1, lines)) {
if (LoadVMOptionsFile(buffer1, user_lines)) {
vmOptionsFile = buffer1;
if (std::find(lines.begin(), lines.end(), std::string("-ea")) == lines.end()) {
std::vector<std::string> lines2;
if (LoadVMOptionsFile(bin_vmoptions, lines2)) {
lines.insert(lines.begin(), lines2.begin(), lines2.end());
}
}
else {
LoadStringA(hInst, IDS_VM_OPTIONS_PATH, buffer1, _MAX_PATH);
ExpandEnvironmentStringsA(buffer1, buffer2, _MAX_PATH);
char *exeParentEnd = strrchr(bin_vmoptions, '\\');
strcat_s(buffer2, exeParentEnd);
if (LoadVMOptionsFile(buffer2, user_lines)) {
vmOptionsFile = buffer2;
}
}
}
// 3. <config_directory>\<exe_name>.vmoptions
if (vmOptionsFile == NULL) {
LoadStringA(hInst, IDS_VM_OPTIONS_PATH, buffer1, _MAX_PATH);
ExpandEnvironmentStringsA(buffer1, buffer2, _MAX_PATH);
char *exeParentEnd = strrchr(bin_vmoptions, '\\');
strcat_s(buffer2, exeParentEnd);
if (LoadVMOptionsFile(buffer2, lines)) {
vmOptionsFile = buffer2;
}
}
// 4. <IDE_HOME>\bin\<exe_name>.vmoptions [+ <config_directory>\user.vmoptions]
if (vmOptionsFile == NULL) {
if (LoadVMOptionsFile(bin_vmoptions, lines)) {
vmOptionsFile = bin_vmoptions;
}
char *p = strrchr(buffer2, '\\');
strcpy_s(p, _MAX_PATH - (p - buffer2), "\\user.vmoptions");
if (LoadVMOptionsFile(buffer2, lines)) {
vmOptionsFile = buffer2;
if (!user_lines.empty()) {
if (!lines.empty()) {
bool (*GC_lookup)(std::string &) = [](std::string &s){
return strncmp(s.c_str(), "-XX:+Use", 8) == 0 && strcmp(s.c_str() + s.length() - 2, "GC") == 0;
};
if (std::find_if(user_lines.begin(), user_lines.end(), GC_lookup) != user_lines.end()) {
lines.erase(std::remove_if(lines.begin(), lines.end(), GC_lookup), lines.end());
}
}
lines.insert(lines.end(), user_lines.begin(), user_lines.end());
}
if (vmOptionsFile != NULL) {