diff --git a/platform/platform-impl/src/com/intellij/diagnostic/VMOptions.java b/platform/platform-impl/src/com/intellij/diagnostic/VMOptions.java index 761078002fff..1d447b61ae83 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/VMOptions.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/VMOptions.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.lang.management.ManagementFactory; import java.util.Collections; import java.util.List; +import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -90,17 +91,30 @@ public class VMOptions { writeGeneralOption(Pattern.compile("-D" + option + separator + "(true|false)*([a-zA-Z0-9]*)"), "-D" + option + separator + value); } + public static void writeEnableCDSArchiveOption(@NotNull final String archivePath) { + writeGeneralOptions( + Function.identity() + .andThen(replaceOrAddOption(Pattern.compile("-Xshare:.*"), "-Xshare:auto")) + .andThen(replaceOrAddOption(Pattern.compile("-XX:\\+UnlockDiagnosticVMOptions"), "-XX:+UnlockDiagnosticVMOptions")) + .andThen(replaceOrAddOption(Pattern.compile("-XX:SharedArchiveFile=.*"), "-XX:SharedArchiveFile=" + archivePath)) + ); + } + + public static void writeDisableCDSArchiveOption() { + writeGeneralOptions( + Function.identity() + .andThen(replaceOrAddOption(Pattern.compile("-Xshare:.*\\r?\\n?"), "")) + .andThen(replaceOrAddOption(Pattern.compile("-XX:SharedArchiveFile=.*\\r?\\n?"), "")) + ); + } private static void writeGeneralOption(@NotNull Pattern pattern, @NotNull String value) { - File file = getWriteFile(); - if (file == null) { - LOG.warn("VM options file not configured"); - return; - } - - try { - String content = file.exists() ? FileUtil.loadFile(file) : read(); + writeGeneralOptions(replaceOrAddOption(pattern, value)); + } + @NotNull + private static Function replaceOrAddOption(@NotNull Pattern pattern, @NotNull String value) { + return content -> { if (!StringUtil.isEmptyOrSpaces(content)) { Matcher m = pattern.matcher(content); if (m.find()) { @@ -109,7 +123,7 @@ public class VMOptions { m.appendTail(b); content = b.toString(); } - else { + else if (!StringUtil.isEmptyOrSpaces(value)) { content = StringUtil.trimTrailing(content) + SystemProperties.getLineSeparator() + value; } } @@ -117,6 +131,21 @@ public class VMOptions { content = value; } + return content; + }; + } + + private static void writeGeneralOptions(@NotNull Function transformContent) { + File file = getWriteFile(); + if (file == null) { + LOG.warn("VM options file not configured"); + return; + } + + try { + String content = file.exists() ? FileUtil.loadFile(file) : read(); + content = transformContent.apply(content); + if (file.exists()) { FileUtil.setReadOnlyAttribute(file.getPath(), false); } diff --git a/platform/platform-tests/testSrc/com/intellij/diagnostic/VMOptionsTest.java b/platform/platform-tests/testSrc/com/intellij/diagnostic/VMOptionsTest.java index ea516b4d2e59..4a91f6dde7f9 100644 --- a/platform/platform-tests/testSrc/com/intellij/diagnostic/VMOptionsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/diagnostic/VMOptionsTest.java @@ -16,17 +16,23 @@ package com.intellij.diagnostic; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.rules.TempDirectory; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import com.intellij.util.containers.ContainerUtil; +import kotlin.collections.ArraysKt; +import org.jetbrains.annotations.NotNull; +import org.junit.*; import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class VMOptionsTest { @Rule public TempDirectory myTempDir = new TempDirectory(); @@ -132,4 +138,149 @@ public class VMOptionsTest { assertThat(FileUtil.loadFile(myFile)).isEqualToIgnoringWhitespace("-Xmx1024m -XX:MaxMetaspaceSize=256m"); } + + @Test + public void testWritingCDSArchiveFileFromScratch() throws IOException { + FileUtil.delete(myFile); + + String myCDSFile = "a/b/c/cds-for-test.jsa"; + VMOptions.writeEnableCDSArchiveOption(myCDSFile); + + String text = FileUtil.loadFile(myFile); + + assertEquals("-Xshare:auto\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "-XX:SharedArchiveFile=a/b/c/cds-for-test.jsa", + StringUtil.convertLineSeparators(text)); + } + + @Test + public void testWritingCDSArchiveFileFromXdumpClash() throws IOException { + FileUtil.writeToFile(myFile, "-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-Xshare:dump\n" + + "junk"); + + String myCDSFile = "a/b/c/cds-for-test.jsa"; + VMOptions.writeEnableCDSArchiveOption(myCDSFile); + + String text = FileUtil.loadFile(myFile); + assertEquals("-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-Xshare:auto\n" + + "junk\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "-XX:SharedArchiveFile=a/b/c/cds-for-test.jsa", + StringUtil.convertLineSeparators(text)); + } + + @Test + public void testWritingCDSArchiveFileFromXXClash() throws IOException { + FileUtil.writeToFile(myFile, "-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "junk"); + + String myCDSFile = "a/b/c/cds-for-test.jsa"; + VMOptions.writeEnableCDSArchiveOption(myCDSFile); + + String text = FileUtil.loadFile(myFile); + System.out.println(text); + + assertEquals("-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "junk\n" + + "-Xshare:auto\n" + + "-XX:SharedArchiveFile=a/b/c/cds-for-test.jsa", + StringUtil.convertLineSeparators(text)); + } + + @Test + public void testWritingCDSArchiveFileFromArchiveClash() throws IOException { + FileUtil.writeToFile(myFile, "-someOption\n-Xmx512m\n-XX:MaxMetaspaceSize=128m\n-anotherOption\n-XX:SharedArchiveFile=foo-bar\njunk"); + + String myCDSFile = "cds-for-test.jsa"; + VMOptions.writeEnableCDSArchiveOption(myCDSFile); + + String text = FileUtil.loadFile(myFile); + System.out.println(text); + assertEquals("-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:SharedArchiveFile=cds-for-test.jsa\n" + + "junk\n" + + "-Xshare:auto\n" + + "-XX:+UnlockDiagnosticVMOptions", + StringUtil.convertLineSeparators(text)); + } + + + @Test + public void testWritingCDSDisableScratch() throws IOException { + FileUtil.writeToFile(myFile, ""); + + VMOptions.writeDisableCDSArchiveOption(); + + String text = FileUtil.loadFile(myFile); + assertEquals("", + StringUtil.convertLineSeparators(text)); + } + + @Test + public void testWritingCDSDisableFull() throws IOException { + FileUtil.writeToFile(myFile, "-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "junk\n" + + "-Xshare:auto\n" + + "junk2\n" + + "-XX:SharedArchiveFile=a/b/c/cds-for-test.jsa\n" + + "junk3"); + + VMOptions.writeDisableCDSArchiveOption(); + + //let's make sure we do not remove anything extra + assertEquals("-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "junk\n" + + "junk2\n" + + "junk3", StringUtil.convertLineSeparators(FileUtil.loadFile(myFile))); + } + + @Test + public void testWritingCDSDisableXShare() throws IOException { + FileUtil.writeToFile(myFile, "-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "-Xshare:dump\n" + + "-XX:SharedArchiveFile=545\njunk"); + + VMOptions.writeDisableCDSArchiveOption(); + + //let's make sure we do not remove anything extra + assertEquals("-someOption\n" + + "-Xmx512m\n" + + "-XX:MaxMetaspaceSize=128m\n" + + "-anotherOption\n" + + "-XX:+UnlockDiagnosticVMOptions\n" + + "junk", + StringUtil.convertLineSeparators(FileUtil.loadFile(myFile))); + } } \ No newline at end of file