diff --git a/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyFactoryImpl.java b/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyFactoryImpl.java index 9234e8506441..1529facf5379 100644 --- a/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyFactoryImpl.java +++ b/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyFactoryImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.runners; import com.intellij.execution.ExecutionException; @@ -12,11 +12,11 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.JavaSdkVersionUtil; import com.intellij.openapi.projectRoots.ex.JavaSdkUtil; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.rt.execution.application.AppMainV2; -import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; public final class ProcessProxyFactoryImpl extends ProcessProxyFactory { private static final boolean ourMayUseLauncher = !Boolean.getBoolean("idea.no.launcher"); @@ -27,14 +27,13 @@ public final class ProcessProxyFactoryImpl extends ProcessProxyFactory { String mainClass = javaParameters.getMainClass(); if (ourMayUseLauncher && mainClass != null) { - String rtJarPath = JavaSdkUtil.getIdeaRtJarPath(); - boolean runtimeJarFile = new File(rtJarPath).isFile() && FileUtil.isAncestor(PathManager.getHomePath(), rtJarPath, true); + var rtJarPath = Path.of(JavaSdkUtil.getIdeaRtJarPath()); + var runtimeJarFile = Files.isRegularFile(rtJarPath) && rtJarPath.startsWith(PathManager.getHomePath()); if (runtimeJarFile || javaParameters.getModuleName() == null) { try { ProcessProxyImpl proxy = new ProcessProxyImpl(StringUtil.getShortName(mainClass)); String port = String.valueOf(proxy.getPortNumber()); - String binPath = proxy.getBinPath(); JavaSdkVersion jdkVersion = JavaSdkVersionUtil.getJavaSdkVersion(javaParameters.getJdk()); if (jdkVersion != null && !jdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) { throw new ExecutionException(JavaBundle.message("error.message.ide.does.not.support.starting.processes.using.old.java", @@ -42,14 +41,13 @@ public final class ProcessProxyFactoryImpl extends ProcessProxyFactory { } if (runtimeJarFile) { - javaParameters.getVMParametersList().add("-javaagent:" + rtJarPath + '=' + port + ':' + binPath); + javaParameters.getVMParametersList().add("-javaagent:" + rtJarPath + '=' + port); } else { JavaSdkUtil.addRtJar(javaParameters.getClassPath()); ParametersList vmParametersList = javaParameters.getVMParametersList(); vmParametersList.defineProperty(AppMainV2.LAUNCHER_PORT_NUMBER, port); - vmParametersList.defineProperty(AppMainV2.LAUNCHER_BIN_PATH, binPath); boolean isJava21preview = JavaSdkVersion.JDK_21.equals(jdkVersion) && javaParameters.getVMParametersList().getParameters().contains(JavaParameters.JAVA_ENABLE_PREVIEW_PROPERTY); @@ -79,4 +77,4 @@ public final class ProcessProxyFactoryImpl extends ProcessProxyFactory { public ProcessProxy getAttachedProxy(ProcessHandler processHandler) { return ProcessProxyImpl.KEY.get(processHandler); } -} \ No newline at end of file +} diff --git a/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java b/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java index 45df20c986be..8b66ed71bfa8 100644 --- a/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java +++ b/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java @@ -1,15 +1,13 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.runners; import com.intellij.execution.process.BaseOSProcessHandler; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.process.UnixProcessManager; -import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.ThrowableRunnable; -import com.intellij.util.system.CpuArch; import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -21,12 +19,10 @@ import java.nio.channels.AsynchronousServerSocketChannel; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.nio.charset.StandardCharsets; -import java.nio.file.Path; import java.util.concurrent.TimeUnit; final class ProcessProxyImpl implements ProcessProxy { static final Key KEY = Key.create("ProcessProxyImpl"); - private static final Path ourBreakgenHelper = SystemInfo.isWindows ? PathManager.findBinFile("breakgen.dll") : null; private final AsynchronousChannelGroup myGroup; private final int myPort; @@ -37,7 +33,7 @@ final class ProcessProxyImpl implements ProcessProxy { ProcessProxyImpl(String mainClass) throws IOException { myGroup = AsynchronousChannelGroup.withFixedThreadPool(1, r -> new Thread(r, "Process Proxy: " + mainClass)); - AsynchronousServerSocketChannel channel = AsynchronousServerSocketChannel.open(myGroup) + @SuppressWarnings("resource") var channel = AsynchronousServerSocketChannel.open(myGroup) .bind(new InetSocketAddress("127.0.0.1", 0)) .setOption(StandardSocketOptions.SO_REUSEADDR, true); myPort = ((InetSocketAddress)channel.getLocalAddress()).getPort(); @@ -73,6 +69,7 @@ final class ProcessProxyImpl implements ProcessProxy { }); } + @SuppressWarnings("SameParameterValue") private void writeLine(String s) { execute(() -> { ByteBuffer out = ByteBuffer.wrap((s + '\n').getBytes(StandardCharsets.US_ASCII)); @@ -82,24 +79,8 @@ final class ProcessProxyImpl implements ProcessProxy { }); } - String getBinPath() { - if (SystemInfo.isWindows) { - if (ourBreakgenHelper != null) { - return ourBreakgenHelper.getParent().toString(); - } - } - return PathManager.getBinPath(); - } - @Override public boolean canSendBreak() { - if (SystemInfo.isWindows && (CpuArch.isArm64() || CpuArch.isIntel64() || CpuArch.isIntel32())) { // see also: `AppMainV2#loadHelper` - synchronized (myLock) { - if (myConnection == null) return false; - } - return ourBreakgenHelper != null; - } - if (SystemInfo.isUnix) { synchronized (myLock) { return myPid > 0; @@ -118,10 +99,7 @@ final class ProcessProxyImpl implements ProcessProxy { @Override public void sendBreak() { - if (SystemInfo.isWindows) { - writeLine("BREAK"); - } - else if (SystemInfo.isUnix) { + if (!SystemInfo.isWindows) { int pid; synchronized (myLock) { pid = myPid; diff --git a/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java b/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java index b1a72f0289f2..22ec2bed388e 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java +++ b/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java @@ -1,8 +1,7 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.rt.execution.application; import java.io.BufferedReader; -import java.io.File; import java.io.InputStreamReader; import java.lang.instrument.Instrumentation; import java.lang.reflect.Constructor; @@ -17,54 +16,24 @@ import java.util.*; */ public final class AppMainV2 { public static final String LAUNCHER_PORT_NUMBER = "idea.launcher.port"; - public static final String LAUNCHER_BIN_PATH = "idea.launcher.bin.path"; public static final String LAUNCHER_USE_JDK_21_PREVIEW = "idea.launcher.use.21.preview"; private static final String LAUNCHER_MAIN_CLASS = "idea.launcher.main.class"; - private static native void triggerControlBreak(); - - private static boolean loadHelper(String binPath) { - String osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); - if (osName.startsWith("windows")) { - String arch = System.getProperty("os.arch").toLowerCase(Locale.ENGLISH); - //noinspection SpellCheckingInspection - String libName = "x86_64".equals(arch) || "amd64".equals(arch) ? "breakgen64.dll" : - "aarch64".equals(arch) || "arm64".equals(arch) ? "breakgen64a.dll" : - "i386".equals(arch) || "x86".equals(arch) ? "breakgen.dll" : - null; // see also: `ProcessProxyImpl#canSendBreak` - if (libName != null) { - File libFile = new File(binPath, libName); - if (libFile.isFile()) { - System.load(libFile.getAbsolutePath()); - return true; - } - } - } - - return false; - } - - private static void startMonitor(final int portNumber, final boolean helperLibLoaded) { + private static void startMonitor(final int portNumber) { Thread t = new Thread("Monitor Ctrl-Break") { @Override public void run() { - try { - try (Socket client = new Socket("127.0.0.1", portNumber)) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII"))) { - while (true) { - String msg = reader.readLine(); - if (msg == null || "TERM".equals(msg)) { - return; - } - else if ("BREAK".equals(msg)) { - if (helperLibLoaded) { - triggerControlBreak(); - } - } - else if ("STOP".equals(msg)) { - System.exit(1); - } - } + try ( + Socket client = new Socket("127.0.0.1", portNumber); + BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII")) + ) { + while (true) { + String msg = reader.readLine(); + if (msg == null || "TERM".equals(msg)) { + return; + } + else if ("STOP".equals(msg)) { + System.exit(1); } } } @@ -77,9 +46,8 @@ public final class AppMainV2 { public static void main(String[] args) throws Throwable { try { - boolean helperLibLoaded = loadHelper(System.getProperty(LAUNCHER_BIN_PATH)); int portNumber = Integer.parseInt(System.getProperty(LAUNCHER_PORT_NUMBER)); - startMonitor(portNumber, helperLibLoaded); + startMonitor(portNumber); } catch (Throwable t) { System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')'); @@ -261,10 +229,8 @@ public final class AppMainV2 { public static void premain(String args) { try { int p = args.indexOf(':'); - if (p < 0) throw new IllegalArgumentException("incorrect parameter: " + args); - boolean helperLibLoaded = loadHelper(args.substring(p + 1)); - int portNumber = Integer.parseInt(args.substring(0, p)); - startMonitor(portNumber, helperLibLoaded); + int portNumber = Integer.parseInt(p > 0 ? args.substring(0, p) : args); + startMonitor(portNumber); } catch (Throwable t) { System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');