From 9410eee446cc6950f881a9bac15fd8e7888f9a49 Mon Sep 17 00:00:00 2001 From: gabilang Date: Mon, 4 Dec 2023 11:47:16 +0530 Subject: [PATCH 1/8] Fix profiler crashes in windows --- .../ballerina/runtime/profiler/Profiler.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java index 51b0d0a00abe..7f5e000e62f7 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java @@ -44,6 +44,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.jar.JarFile; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -210,7 +211,8 @@ private void addToUsedArgs(String[] args, List usedArgs, int i) { private void extractProfiler() throws ProfilerException { OUT_STREAM.printf("%s[1/6] Initializing...%s%n", Constants.ANSI_CYAN, Constants.ANSI_RESET); try { - new ProcessBuilder("jar", "xvf", "Profiler.jar", "io/ballerina/runtime/profiler/runtime").start().waitFor(); + Path profilerRuntimePath = Paths.get("io/ballerina/runtime/profiler/runtime"); + new ProcessBuilder("jar", "xvf", "Profiler.jar", profilerRuntimePath.toString()).start().waitFor(); } catch (IOException | InterruptedException exception) { throw new ProfilerException(exception); } @@ -247,15 +249,16 @@ private void initializeProfiling() throws ProfilerException { if (mainClassPackage == null) { continue; } - if (className.startsWith(mainClassPackage.split("/")[0]) || utilPaths.contains(className)) { + String mainClassPackagePart = mainClassPackage.split(Pattern.quote(File.separator))[0]; + if (className.startsWith(mainClassPackagePart) || utilPaths.contains(className)) { try (InputStream inputStream = jarFile.getInputStream(jarFile.getJarEntry(className))) { byte[] code = profilerMethodWrapper.modifyMethods(inputStream); profilerClassLoader.loadClass(code); - usedPaths.add(className.replace(Constants.CLASS_SUFFIX, "").replace("/", ".")); + usedPaths.add(className.replace(Constants.CLASS_SUFFIX, "").replace(File.separator, ".")); profilerMethodWrapper.printCode(className, code, getFileNameWithoutExtension(balJarName)); } } - if (className.endsWith("/$_init.class")) { + if (className.endsWith(File.separator + "$_init.class")) { moduleCount++; } } @@ -281,7 +284,8 @@ private void modifyJar() throws InterruptedException, IOException { for (String instrumentedFilePath : instrumentedPaths) { FileUtils.deleteDirectory(new File(instrumentedFilePath)); } - FileUtils.deleteDirectory(new File("io/ballerina/runtime/profiler/runtime")); + Path filePath = Paths.get("io/ballerina/runtime/profiler/runtime"); + FileUtils.deleteDirectory(new File(filePath.toString())); profilerMethodWrapper.invokeMethods(profilerDebugArg); } } @@ -315,12 +319,12 @@ private void analyseInstrumentedDirectories(File directory, String absolutePath) } private void updateInstrumentedFile(File fileEntry, String absolutePath) { - String fileEntryString = String.valueOf(fileEntry); + String fileEntryString = fileEntry.getPath(); if (fileEntryString.endsWith(Constants.CLASS_SUFFIX)) { fileEntryString = fileEntryString.replaceAll(absolutePath, ""); - int index = fileEntryString.lastIndexOf('/'); + int index = fileEntryString.lastIndexOf(File.separator); fileEntryString = index == -1 ? "" : fileEntryString.substring(0, index); - String[] fileEntryParts = fileEntryString.split("/"); + String[] fileEntryParts = fileEntryString.split(Pattern.quote(File.separator)); instrumentedPaths.add(fileEntryParts[0]); instrumentedFiles.add(fileEntryString); } @@ -342,7 +346,7 @@ private void findUtilityClasses(ArrayList classNames) { for (String path : utilInitPaths) { if (name.startsWith(path)) { String subPath = name.substring(path.length()); - if (subPath.indexOf('/') == -1) { + if (!subPath.contains(File.separator)) { utilPaths.add(name); } } @@ -353,7 +357,7 @@ private void findUtilityClasses(ArrayList classNames) { private void populateInitPaths(ArrayList classNames) { for (String className : classNames) { if (className.endsWith("$_init.class")) { - String path = className.substring(0, className.lastIndexOf('/') + 1); + String path = className.substring(0, className.lastIndexOf(File.separator) + 1); if (!utilInitPaths.contains(path)) { utilInitPaths.add(path); } From 1c804d6a96533ed0d9a274ffa0f467807b0ee5fe Mon Sep 17 00:00:00 2001 From: gabilang Date: Thu, 7 Dec 2023 10:31:01 +0530 Subject: [PATCH 2/8] Use java.util file separator --- .../java/io/ballerina/runtime/profiler/Profiler.java | 2 +- .../runtime/profiler/codegen/ProfilerClassLoader.java | 4 +++- .../runtime/profiler/codegen/ProfilerClassWriter.java | 8 +++++--- .../runtime/profiler/codegen/ProfilerMethodWrapper.java | 9 +++++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java index 5cc8b4e26394..b486ddf8e284 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java @@ -293,7 +293,7 @@ private void updateInstrumentedFile(File fileEntry, String absolutePath) { String fileEntryString = fileEntry.getPath(); if (fileEntryString.endsWith(Constants.CLASS_SUFFIX)) { fileEntryString = fileEntryString.replaceAll(absolutePath, ""); - int index = fileEntryString.lastIndexOf(File.separator); + int index = fileEntryString.lastIndexOf(File.separatorChar); fileEntryString = index == -1 ? "" : fileEntryString.substring(0, index); String[] fileEntryParts = fileEntryString.split(Pattern.quote(File.separator)); instrumentedPaths.add(fileEntryParts[0]); diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java index 1a24bcc183f1..c0e90e3eee0e 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java @@ -21,6 +21,8 @@ import io.ballerina.runtime.profiler.util.ProfilerException; import org.objectweb.asm.ClassReader; +import java.io.File; + /** * This class is used as a class loader for the Ballerina profiler. * @@ -44,6 +46,6 @@ public void loadClass(byte[] code) { } public String readClassName(final byte[] byteCode) { - return new ClassReader(byteCode).getClassName().replace("/", "."); + return new ClassReader(byteCode).getClassName().replace(File.separator, "."); } } diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java index afdfbe456317..57e7d7fcd086 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java @@ -21,6 +21,8 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; +import java.io.File; + /** * This class is used as a class writer for the Ballerina profiler. * @@ -40,8 +42,8 @@ protected String getCommonSuperClass(String type1, String type2) { Class class1; Class class2; try { - class1 = Class.forName(type1.replace('/', '.'), false, classLoader); - class2 = Class.forName(type2.replace('/', '.'), false, classLoader); + class1 = Class.forName(type1.replace(File.separatorChar, '.'), false, classLoader); + class2 = Class.forName(type2.replace(File.separatorChar, '.'), false, classLoader); } catch (ClassNotFoundException e) { return OBJECT_CLASS; } @@ -56,6 +58,6 @@ protected String getCommonSuperClass(String type1, String type2) { while (!class1.isAssignableFrom(class2)) { class1 = class1.getSuperclass(); } - return class1.getName().replace('.', '/'); + return class1.getName().replace('.', File.separatorChar); } } diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java index 6b1e802a27f0..7ffb612048e9 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java @@ -39,6 +39,7 @@ import java.util.List; import java.util.jar.Attributes; import java.util.jar.Manifest; +import java.util.regex.Pattern; import static io.ballerina.runtime.profiler.util.Constants.CURRENT_DIR_KEY; import static io.ballerina.runtime.profiler.util.Constants.ERROR_STREAM; @@ -78,10 +79,10 @@ public void invokeMethods(String debugArg) throws IOException, InterruptedExcept public String mainClassFinder(URLClassLoader manifestClassLoader) { try { - URL manifestURL = manifestClassLoader.findResource("META-INF/MANIFEST.MF"); + URL manifestURL = manifestClassLoader.findResource("META-INF" + File.separator + "MANIFEST.MF"); Manifest manifest = new Manifest(manifestURL.openStream()); Attributes attributes = manifest.getMainAttributes(); - return attributes.getValue("Main-Class").replace(".$_init", "").replace(".", "/"); + return attributes.getValue("Main-Class").replace(".$_init", "").replace(".", File.separator); } catch (Throwable throwable) { ERROR_STREAM.println(throwable + "%n"); return null; @@ -106,11 +107,11 @@ public byte[] modifyMethods(InputStream inputStream, String className) { // Print out the modified class code public void printCode(String className, byte[] code, String balJarName) { - int lastSlashIndex = className.lastIndexOf('/'); + int lastSlashIndex = className.lastIndexOf(Pattern.quote(File.separator)); String output; if (lastSlashIndex == -1) { output = balJarName; - className = balJarName + "/" + className; + className = balJarName + File.separator + className; } else { output = className.substring(0, lastSlashIndex); } From 2c418109331e722a7597a289acbf580f4ba573a1 Mon Sep 17 00:00:00 2001 From: gabilang Date: Thu, 7 Dec 2023 11:38:29 +0530 Subject: [PATCH 3/8] Fix file not found error --- .../runtime/profiler/codegen/ProfilerMethodWrapper.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java index 7ffb612048e9..64054b71c0b2 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java @@ -39,7 +39,6 @@ import java.util.List; import java.util.jar.Attributes; import java.util.jar.Manifest; -import java.util.regex.Pattern; import static io.ballerina.runtime.profiler.util.Constants.CURRENT_DIR_KEY; import static io.ballerina.runtime.profiler.util.Constants.ERROR_STREAM; @@ -79,7 +78,7 @@ public void invokeMethods(String debugArg) throws IOException, InterruptedExcept public String mainClassFinder(URLClassLoader manifestClassLoader) { try { - URL manifestURL = manifestClassLoader.findResource("META-INF" + File.separator + "MANIFEST.MF"); + URL manifestURL = manifestClassLoader.findResource("META-INF/MANIFEST.MF"); Manifest manifest = new Manifest(manifestURL.openStream()); Attributes attributes = manifest.getMainAttributes(); return attributes.getValue("Main-Class").replace(".$_init", "").replace(".", File.separator); @@ -107,7 +106,7 @@ public byte[] modifyMethods(InputStream inputStream, String className) { // Print out the modified class code public void printCode(String className, byte[] code, String balJarName) { - int lastSlashIndex = className.lastIndexOf(Pattern.quote(File.separator)); + int lastSlashIndex = className.lastIndexOf(File.separatorChar); String output; if (lastSlashIndex == -1) { output = balJarName; From 928003c61e56f92a890ab92a4ebc7665467176cf Mon Sep 17 00:00:00 2001 From: gabilang Date: Wed, 13 Dec 2023 08:54:27 +0530 Subject: [PATCH 4/8] Fix regex issues with windows file separator --- .../java/io/ballerina/runtime/profiler/Profiler.java | 11 +++++------ .../runtime/profiler/codegen/ProfilerClassLoader.java | 4 +--- .../runtime/profiler/codegen/ProfilerClassWriter.java | 8 +++----- .../profiler/codegen/ProfilerMethodWrapper.java | 6 +++--- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java index b486ddf8e284..3004d8fc2f03 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java @@ -223,8 +223,7 @@ private void initializeProfiling() throws ProfilerException { if (mainClassPackage == null || className.contains("$gen$")) { continue; } - String mainClassPackagePart = mainClassPackage.split(Pattern.quote(File.separator))[0]; - if (className.startsWith(mainClassPackagePart) || utilPaths.contains(className)) { + if (className.startsWith(mainClassPackage.split("/")[0]) || utilPaths.contains(className)) { try (InputStream inputStream = jarFile.getInputStream(jarFile.getJarEntry(className))) { String sourceClassName = className.replace(Constants.CLASS_SUFFIX, ""); byte[] code = profilerMethodWrapper.modifyMethods(inputStream, sourceClassName); @@ -232,7 +231,7 @@ private void initializeProfiling() throws ProfilerException { profilerMethodWrapper.printCode(className, code, getFileNameWithoutExtension(balJarName)); } } - if (className.endsWith(File.separator + "$_init.class")) { + if (className.endsWith("/$_init.class")) { moduleCount++; } } @@ -292,7 +291,7 @@ private void analyseInstrumentedDirectories(File directory, String absolutePath) private void updateInstrumentedFile(File fileEntry, String absolutePath) { String fileEntryString = fileEntry.getPath(); if (fileEntryString.endsWith(Constants.CLASS_SUFFIX)) { - fileEntryString = fileEntryString.replaceAll(absolutePath, ""); + fileEntryString = fileEntryString.replaceAll(Pattern.quote(absolutePath), ""); int index = fileEntryString.lastIndexOf(File.separatorChar); fileEntryString = index == -1 ? "" : fileEntryString.substring(0, index); String[] fileEntryParts = fileEntryString.split(Pattern.quote(File.separator)); @@ -317,7 +316,7 @@ private void findUtilityClasses(ArrayList classNames) { for (String path : utilInitPaths) { if (name.startsWith(path)) { String subPath = name.substring(path.length()); - if (!subPath.contains(File.separator)) { + if (subPath.indexOf('/') == -1) { utilPaths.add(name); } } @@ -328,7 +327,7 @@ private void findUtilityClasses(ArrayList classNames) { private void populateInitPaths(ArrayList classNames) { for (String className : classNames) { if (className.endsWith("$_init.class")) { - String path = className.substring(0, className.lastIndexOf(File.separator) + 1); + String path = className.substring(0, className.lastIndexOf('/') + 1); if (!utilInitPaths.contains(path)) { utilInitPaths.add(path); } diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java index c0e90e3eee0e..1a24bcc183f1 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassLoader.java @@ -21,8 +21,6 @@ import io.ballerina.runtime.profiler.util.ProfilerException; import org.objectweb.asm.ClassReader; -import java.io.File; - /** * This class is used as a class loader for the Ballerina profiler. * @@ -46,6 +44,6 @@ public void loadClass(byte[] code) { } public String readClassName(final byte[] byteCode) { - return new ClassReader(byteCode).getClassName().replace(File.separator, "."); + return new ClassReader(byteCode).getClassName().replace("/", "."); } } diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java index 57e7d7fcd086..afdfbe456317 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerClassWriter.java @@ -21,8 +21,6 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; -import java.io.File; - /** * This class is used as a class writer for the Ballerina profiler. * @@ -42,8 +40,8 @@ protected String getCommonSuperClass(String type1, String type2) { Class class1; Class class2; try { - class1 = Class.forName(type1.replace(File.separatorChar, '.'), false, classLoader); - class2 = Class.forName(type2.replace(File.separatorChar, '.'), false, classLoader); + class1 = Class.forName(type1.replace('/', '.'), false, classLoader); + class2 = Class.forName(type2.replace('/', '.'), false, classLoader); } catch (ClassNotFoundException e) { return OBJECT_CLASS; } @@ -58,6 +56,6 @@ protected String getCommonSuperClass(String type1, String type2) { while (!class1.isAssignableFrom(class2)) { class1 = class1.getSuperclass(); } - return class1.getName().replace('.', File.separatorChar); + return class1.getName().replace('.', '/'); } } diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java index 64054b71c0b2..6b1e802a27f0 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java @@ -81,7 +81,7 @@ public String mainClassFinder(URLClassLoader manifestClassLoader) { URL manifestURL = manifestClassLoader.findResource("META-INF/MANIFEST.MF"); Manifest manifest = new Manifest(manifestURL.openStream()); Attributes attributes = manifest.getMainAttributes(); - return attributes.getValue("Main-Class").replace(".$_init", "").replace(".", File.separator); + return attributes.getValue("Main-Class").replace(".$_init", "").replace(".", "/"); } catch (Throwable throwable) { ERROR_STREAM.println(throwable + "%n"); return null; @@ -106,11 +106,11 @@ public byte[] modifyMethods(InputStream inputStream, String className) { // Print out the modified class code public void printCode(String className, byte[] code, String balJarName) { - int lastSlashIndex = className.lastIndexOf(File.separatorChar); + int lastSlashIndex = className.lastIndexOf('/'); String output; if (lastSlashIndex == -1) { output = balJarName; - className = balJarName + File.separator + className; + className = balJarName + "/" + className; } else { output = className.substring(0, lastSlashIndex); } From 8527eb6cb8099a1be1cc20c9bbec4aa9c7cc134b Mon Sep 17 00:00:00 2001 From: gabilang Date: Thu, 14 Dec 2023 08:24:47 +0530 Subject: [PATCH 5/8] Fix file deletion issue due to windows lock --- .../main/java/io/ballerina/cli/task/RunProfilerTask.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java index f6e562fde697..6badd5f2637e 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java @@ -31,6 +31,7 @@ import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import static io.ballerina.cli.launcher.LauncherUtils.createLauncherException; import static io.ballerina.cli.utils.DebugUtils.getDebugArgs; @@ -51,6 +52,8 @@ public class RunProfilerTask implements Task { private final PrintStream err; private static final String JAVA_OPTS = "JAVA_OPTS"; private static final String CURRENT_DIR_KEY = "current.dir"; + private static final Boolean isWindows = System.getProperty("os.name").toLowerCase(Locale.getDefault()) + .contains("win"); public RunProfilerTask(PrintStream errStream) { this.err = errStream; @@ -93,6 +96,11 @@ private void initiateProfiler(Project project) { if (exitValue != 0) { throw new RuntimePanicException(exitValue); } + if (isWindows) { + new ProcessBuilder("cmd", "/C", "del", targetPath.toString()).inheritIO().start().waitFor(); + } else { + Files.deleteIfExists(targetPath); + } } catch (IOException | InterruptedException e) { throw createLauncherException("error occurred while running the profiler ", e); } From ecb87a14ebd0a752af6295a29c0536c791473cfc Mon Sep 17 00:00:00 2001 From: gabilang Date: Thu, 14 Dec 2023 08:56:43 +0530 Subject: [PATCH 6/8] Remove unused cmd argument --- .../main/java/io/ballerina/runtime/profiler/Profiler.java | 7 ------- .../main/java/io/ballerina/cli/task/RunProfilerTask.java | 2 -- 2 files changed, 9 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java index 3004d8fc2f03..44b20c68c9cc 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java @@ -60,7 +60,6 @@ public class Profiler { private final long profilerStartTime; private String balJarArgs = null; private String balJarName = null; - private String targetDir = null; private String sourceRoot = null; private String profilerDebugArg = null; private final List instrumentedPaths = new ArrayList<>(); @@ -97,8 +96,6 @@ private void addShutdownHookAndCleanup() { OUT_STREAM.println("--------------------------------------------------------------------------------"); } catch (IOException e) { throw new ProfilerException("Error occurred while generating the output", e); - } finally { - deleteFileIfExists(targetDir); } })); } @@ -141,10 +138,6 @@ private void handleProfilerArguments(String[] args) { this.balJarArgs = extractBalJarArgs(args[i + 1]); addToUsedArgs(args, usedArgs, i); } - case "--target" -> { - this.targetDir = args[i + 1]; - addToUsedArgs(args, usedArgs, i); - } case "--source-root" -> { this.sourceRoot = args[i + 1]; addToUsedArgs(args, usedArgs, i); diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java index 6badd5f2637e..782cf4b7c5cf 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java @@ -78,8 +78,6 @@ private void initiateProfiler(Project project) { // Sets classpath with executable thin jar and all dependency jar paths. commands.add("--file"); commands.add(getPackageJarName(project, projectKind)); - commands.add("--target"); - commands.add(targetPath.toString()); commands.add("--source-root"); commands.add(getProjectPath(project).toString()); if (isInProfileDebugMode()) { From c468116760dd13a110c8739486ddb102880a9c8c Mon Sep 17 00:00:00 2001 From: gabilang Date: Thu, 14 Dec 2023 15:25:44 +0530 Subject: [PATCH 7/8] Use Files.deleteIfExists for jar removals --- .../java/io/ballerina/runtime/profiler/Profiler.java | 2 +- .../io/ballerina/runtime/profiler/ui/HttpServer.java | 3 ++- .../main/java/io/ballerina/cli/task/RunProfilerTask.java | 9 +-------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java index 44b20c68c9cc..7f331d1944b9 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java @@ -83,7 +83,7 @@ private void addShutdownHookAndCleanup() { try { long profilerTotalTime = TimeUnit.MILLISECONDS.convert(System.nanoTime(), TimeUnit.NANOSECONDS) - profilerStartTime; - deleteFileIfExists(Constants.TEMP_JAR_FILE_NAME); + Files.deleteIfExists(Paths.get(Constants.TEMP_JAR_FILE_NAME)); OUT_STREAM.printf("%s[6/6] Generating output...%s%n", Constants.ANSI_CYAN, Constants.ANSI_RESET); JsonParser jsonParser = new JsonParser(); HttpServer httpServer = new HttpServer(); diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java index 1ed16745e255..67302aa5fcac 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java @@ -20,6 +20,7 @@ import io.ballerina.runtime.profiler.util.Constants; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -36,7 +37,7 @@ public class HttpServer { public void initializeHTMLExport(String sourceRoot) throws IOException { OUT_STREAM.printf(" ○ Output: " + Constants.ANSI_YELLOW + - "%s/ProfilerOutput.html" + Constants.ANSI_RESET + "%n", sourceRoot); + "%s" + File.separator + "ProfilerOutput.html" + Constants.ANSI_RESET + "%n", sourceRoot); String content = FileUtils.readFileAsString(PERFORMANCE_JSON); FrontEnd frontEnd = new FrontEnd(); String htmlData = frontEnd.getSiteData(content); diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java index 782cf4b7c5cf..04ab6e1272cb 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java @@ -31,7 +31,6 @@ import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import static io.ballerina.cli.launcher.LauncherUtils.createLauncherException; import static io.ballerina.cli.utils.DebugUtils.getDebugArgs; @@ -52,8 +51,6 @@ public class RunProfilerTask implements Task { private final PrintStream err; private static final String JAVA_OPTS = "JAVA_OPTS"; private static final String CURRENT_DIR_KEY = "current.dir"; - private static final Boolean isWindows = System.getProperty("os.name").toLowerCase(Locale.getDefault()) - .contains("win"); public RunProfilerTask(PrintStream errStream) { this.err = errStream; @@ -94,11 +91,7 @@ private void initiateProfiler(Project project) { if (exitValue != 0) { throw new RuntimePanicException(exitValue); } - if (isWindows) { - new ProcessBuilder("cmd", "/C", "del", targetPath.toString()).inheritIO().start().waitFor(); - } else { - Files.deleteIfExists(targetPath); - } + Files.deleteIfExists(targetPath); } catch (IOException | InterruptedException e) { throw createLauncherException("error occurred while running the profiler ", e); } From 7c33bc90f11167e218637679407e71a2bacbf5d1 Mon Sep 17 00:00:00 2001 From: gabilang Date: Mon, 18 Dec 2023 09:45:42 +0530 Subject: [PATCH 8/8] Fix stream closing and console log output --- .../io/ballerina/runtime/profiler/Profiler.java | 6 +++--- .../profiler/codegen/ProfilerMethodWrapper.java | 4 ++-- .../runtime/profiler/ui/HttpServer.java | 4 ++-- .../io/ballerina/cli/task/RunProfilerTask.java | 7 ++++++- .../test/profiler/ProfilerTest.java | 16 ++++++++-------- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java index 7f331d1944b9..9c43bdcc953a 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/Profiler.java @@ -90,7 +90,7 @@ private void addShutdownHookAndCleanup() { String cpuFilePath = Paths.get(currentDir, CPU_PRE_JSON).toString(); jsonParser.initializeCPUParser(cpuFilePath); deleteFileIfExists(cpuFilePath); - OUT_STREAM.printf(" ○ Execution time: %d seconds %n", profilerTotalTime / 1000); + OUT_STREAM.printf(" Execution time: %d seconds %n", profilerTotalTime / 1000); httpServer.initializeHTMLExport(this.sourceRoot); deleteFileIfExists(PERFORMANCE_JSON); OUT_STREAM.println("--------------------------------------------------------------------------------"); @@ -228,8 +228,8 @@ private void initializeProfiling() throws ProfilerException { moduleCount++; } } - OUT_STREAM.printf(" ○ Instrumented module count: %d%n", moduleCount); - OUT_STREAM.printf(" ○ Instrumented function count: %d%n", balFunctionCount); + OUT_STREAM.printf(" Instrumented module count: %d%n", moduleCount); + OUT_STREAM.printf(" Instrumented function count: %d%n", balFunctionCount); modifyJar(); } catch (Throwable throwable) { throw new ProfilerException(throwable); diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java index 6b1e802a27f0..239d3f1da78d 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/codegen/ProfilerMethodWrapper.java @@ -69,8 +69,8 @@ public void invokeMethods(String debugArg) throws IOException, InterruptedExcept processBuilder.directory(new File(System.getenv(CURRENT_DIR_KEY))); Process process = processBuilder.start(); OUT_STREAM.printf(Constants.ANSI_CYAN + "[5/6] Running executable..." + Constants.ANSI_RESET + "%n"); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), - StandardCharsets.UTF_8))) { + try (InputStreamReader streamReader = new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8); + BufferedReader reader = new BufferedReader(streamReader)) { reader.lines().forEach(OUT_STREAM::println); } process.waitFor(); diff --git a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java index 67302aa5fcac..24f78b669d9f 100644 --- a/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java +++ b/bvm/ballerina-profiler/src/main/java/io/ballerina/runtime/profiler/ui/HttpServer.java @@ -36,8 +36,8 @@ public class HttpServer { public void initializeHTMLExport(String sourceRoot) throws IOException { - OUT_STREAM.printf(" ○ Output: " + Constants.ANSI_YELLOW + - "%s" + File.separator + "ProfilerOutput.html" + Constants.ANSI_RESET + "%n", sourceRoot); + OUT_STREAM.printf(" Output: " + Constants.ANSI_YELLOW + "%s" + File.separator + "ProfilerOutput.html" + + Constants.ANSI_RESET + "%n", sourceRoot); String content = FileUtils.readFileAsString(PERFORMANCE_JSON); FrontEnd frontEnd = new FrontEnd(); String htmlData = frontEnd.getSiteData(content); diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java index 04ab6e1272cb..f21afdcba9b7 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunProfilerTask.java @@ -91,9 +91,14 @@ private void initiateProfiler(Project project) { if (exitValue != 0) { throw new RuntimePanicException(exitValue); } - Files.deleteIfExists(targetPath); } catch (IOException | InterruptedException e) { throw createLauncherException("error occurred while running the profiler ", e); + } finally { + try { + Files.deleteIfExists(targetPath); + } catch (IOException e) { + err.println("error occurred while deleting the profiler.jar file"); + } } } diff --git a/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/profiler/ProfilerTest.java b/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/profiler/ProfilerTest.java index a5f3ae08293c..f6e43d383275 100644 --- a/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/profiler/ProfilerTest.java +++ b/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/profiler/ProfilerTest.java @@ -86,12 +86,12 @@ private List getProfilerLogLeechers(String htmlFilePath) { new LogLeecher("[2/6] Copying executable..."), new LogLeecher("[3/6] Performing analysis..."), new LogLeecher("[4/6] Instrumenting functions..."), - new LogLeecher("○ Instrumented module count: "), - new LogLeecher("○ Instrumented function count: "), + new LogLeecher(" Instrumented module count: "), + new LogLeecher(" Instrumented function count: "), new LogLeecher("[5/6] Running executable..."), new LogLeecher("[6/6] Generating output..."), - new LogLeecher(" ○ Execution time: [1-5] seconds ", true, LogLeecher.LeecherType.INFO), - new LogLeecher("○ Output: "), + new LogLeecher(" Execution time: [1-5] seconds ", true, LogLeecher.LeecherType.INFO), + new LogLeecher(" Output: "), new LogLeecher(htmlFilePath)); } @@ -120,15 +120,15 @@ public void testProfilerExecutionWithKillSignal() throws BallerinaTestException new LogLeecher("[2/6] Copying executable..."), new LogLeecher("[3/6] Performing analysis..."), new LogLeecher("[4/6] Instrumenting functions..."), - new LogLeecher("○ Instrumented module count: "), - new LogLeecher("○ Instrumented function count: "), + new LogLeecher(" Instrumented module count: "), + new LogLeecher(" Instrumented function count: "), new LogLeecher("[5/6] Running executable...")}; Process process = bMainInstance.runCommandAndGetProcess("profile", new String[]{packageName}, envProperties, sourceRoot); LogLeecher[] afterExecleechers = new LogLeecher[]{ new LogLeecher("[6/6] Generating output..."), - new LogLeecher("○ Execution time:"), - new LogLeecher("○ Output: ")}; + new LogLeecher(" Execution time:"), + new LogLeecher(" Output: ")}; ServerLogReader serverInfoLogReader = new ServerLogReader("inputStream", process.getInputStream()); addLogLeechers(beforeExecleechers, serverInfoLogReader); addLogLeechers(afterExecleechers, serverInfoLogReader);