mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
[java] retiring 'breakgen' DLLs from JVM process proxy (IJPL-16521)
(cherry picked from commit 3789c7f569bc1f220aa9c7524d36ac44a3754cf0) IJ-CR-155182 GitOrigin-RevId: a7ff75cc9cc1a54c9c1b1628fb7c89f65cf8cf8d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7efa647a39
commit
e7a6ad4826
@@ -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;
|
package com.intellij.execution.runners;
|
||||||
|
|
||||||
import com.intellij.execution.ExecutionException;
|
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.JavaSdkVersion;
|
||||||
import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
|
import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
|
||||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.rt.execution.application.AppMainV2;
|
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 {
|
public final class ProcessProxyFactoryImpl extends ProcessProxyFactory {
|
||||||
private static final boolean ourMayUseLauncher = !Boolean.getBoolean("idea.no.launcher");
|
private static final boolean ourMayUseLauncher = !Boolean.getBoolean("idea.no.launcher");
|
||||||
@@ -27,14 +27,13 @@ public final class ProcessProxyFactoryImpl extends ProcessProxyFactory {
|
|||||||
String mainClass = javaParameters.getMainClass();
|
String mainClass = javaParameters.getMainClass();
|
||||||
|
|
||||||
if (ourMayUseLauncher && mainClass != null) {
|
if (ourMayUseLauncher && mainClass != null) {
|
||||||
String rtJarPath = JavaSdkUtil.getIdeaRtJarPath();
|
var rtJarPath = Path.of(JavaSdkUtil.getIdeaRtJarPath());
|
||||||
boolean runtimeJarFile = new File(rtJarPath).isFile() && FileUtil.isAncestor(PathManager.getHomePath(), rtJarPath, true);
|
var runtimeJarFile = Files.isRegularFile(rtJarPath) && rtJarPath.startsWith(PathManager.getHomePath());
|
||||||
|
|
||||||
if (runtimeJarFile || javaParameters.getModuleName() == null) {
|
if (runtimeJarFile || javaParameters.getModuleName() == null) {
|
||||||
try {
|
try {
|
||||||
ProcessProxyImpl proxy = new ProcessProxyImpl(StringUtil.getShortName(mainClass));
|
ProcessProxyImpl proxy = new ProcessProxyImpl(StringUtil.getShortName(mainClass));
|
||||||
String port = String.valueOf(proxy.getPortNumber());
|
String port = String.valueOf(proxy.getPortNumber());
|
||||||
String binPath = proxy.getBinPath();
|
|
||||||
JavaSdkVersion jdkVersion = JavaSdkVersionUtil.getJavaSdkVersion(javaParameters.getJdk());
|
JavaSdkVersion jdkVersion = JavaSdkVersionUtil.getJavaSdkVersion(javaParameters.getJdk());
|
||||||
if (jdkVersion != null && !jdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) {
|
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",
|
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) {
|
if (runtimeJarFile) {
|
||||||
javaParameters.getVMParametersList().add("-javaagent:" + rtJarPath + '=' + port + ':' + binPath);
|
javaParameters.getVMParametersList().add("-javaagent:" + rtJarPath + '=' + port);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JavaSdkUtil.addRtJar(javaParameters.getClassPath());
|
JavaSdkUtil.addRtJar(javaParameters.getClassPath());
|
||||||
|
|
||||||
ParametersList vmParametersList = javaParameters.getVMParametersList();
|
ParametersList vmParametersList = javaParameters.getVMParametersList();
|
||||||
vmParametersList.defineProperty(AppMainV2.LAUNCHER_PORT_NUMBER, port);
|
vmParametersList.defineProperty(AppMainV2.LAUNCHER_PORT_NUMBER, port);
|
||||||
vmParametersList.defineProperty(AppMainV2.LAUNCHER_BIN_PATH, binPath);
|
|
||||||
|
|
||||||
boolean isJava21preview = JavaSdkVersion.JDK_21.equals(jdkVersion) &&
|
boolean isJava21preview = JavaSdkVersion.JDK_21.equals(jdkVersion) &&
|
||||||
javaParameters.getVMParametersList().getParameters().contains(JavaParameters.JAVA_ENABLE_PREVIEW_PROPERTY);
|
javaParameters.getVMParametersList().getParameters().contains(JavaParameters.JAVA_ENABLE_PREVIEW_PROPERTY);
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.execution.runners;
|
||||||
|
|
||||||
import com.intellij.execution.process.BaseOSProcessHandler;
|
import com.intellij.execution.process.BaseOSProcessHandler;
|
||||||
import com.intellij.execution.process.ProcessHandler;
|
import com.intellij.execution.process.ProcessHandler;
|
||||||
import com.intellij.execution.process.UnixProcessManager;
|
import com.intellij.execution.process.UnixProcessManager;
|
||||||
import com.intellij.openapi.application.PathManager;
|
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.util.Key;
|
import com.intellij.openapi.util.Key;
|
||||||
import com.intellij.openapi.util.SystemInfo;
|
import com.intellij.openapi.util.SystemInfo;
|
||||||
import com.intellij.util.ThrowableRunnable;
|
import com.intellij.util.ThrowableRunnable;
|
||||||
import com.intellij.util.system.CpuArch;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -21,12 +19,10 @@ import java.nio.channels.AsynchronousServerSocketChannel;
|
|||||||
import java.nio.channels.AsynchronousSocketChannel;
|
import java.nio.channels.AsynchronousSocketChannel;
|
||||||
import java.nio.channels.CompletionHandler;
|
import java.nio.channels.CompletionHandler;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
final class ProcessProxyImpl implements ProcessProxy {
|
final class ProcessProxyImpl implements ProcessProxy {
|
||||||
static final Key<ProcessProxyImpl> KEY = Key.create("ProcessProxyImpl");
|
static final Key<ProcessProxyImpl> KEY = Key.create("ProcessProxyImpl");
|
||||||
private static final Path ourBreakgenHelper = SystemInfo.isWindows ? PathManager.findBinFile("breakgen.dll") : null;
|
|
||||||
|
|
||||||
private final AsynchronousChannelGroup myGroup;
|
private final AsynchronousChannelGroup myGroup;
|
||||||
private final int myPort;
|
private final int myPort;
|
||||||
@@ -37,7 +33,7 @@ final class ProcessProxyImpl implements ProcessProxy {
|
|||||||
|
|
||||||
ProcessProxyImpl(String mainClass) throws IOException {
|
ProcessProxyImpl(String mainClass) throws IOException {
|
||||||
myGroup = AsynchronousChannelGroup.withFixedThreadPool(1, r -> new Thread(r, "Process Proxy: " + mainClass));
|
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))
|
.bind(new InetSocketAddress("127.0.0.1", 0))
|
||||||
.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||||
myPort = ((InetSocketAddress)channel.getLocalAddress()).getPort();
|
myPort = ((InetSocketAddress)channel.getLocalAddress()).getPort();
|
||||||
@@ -73,6 +69,7 @@ final class ProcessProxyImpl implements ProcessProxy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SameParameterValue")
|
||||||
private void writeLine(String s) {
|
private void writeLine(String s) {
|
||||||
execute(() -> {
|
execute(() -> {
|
||||||
ByteBuffer out = ByteBuffer.wrap((s + '\n').getBytes(StandardCharsets.US_ASCII));
|
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
|
@Override
|
||||||
public boolean canSendBreak() {
|
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) {
|
if (SystemInfo.isUnix) {
|
||||||
synchronized (myLock) {
|
synchronized (myLock) {
|
||||||
return myPid > 0;
|
return myPid > 0;
|
||||||
@@ -118,10 +99,7 @@ final class ProcessProxyImpl implements ProcessProxy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendBreak() {
|
public void sendBreak() {
|
||||||
if (SystemInfo.isWindows) {
|
if (!SystemInfo.isWindows) {
|
||||||
writeLine("BREAK");
|
|
||||||
}
|
|
||||||
else if (SystemInfo.isUnix) {
|
|
||||||
int pid;
|
int pid;
|
||||||
synchronized (myLock) {
|
synchronized (myLock) {
|
||||||
pid = myPid;
|
pid = myPid;
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.rt.execution.application;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
@@ -17,57 +16,27 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public final class AppMainV2 {
|
public final class AppMainV2 {
|
||||||
public static final String LAUNCHER_PORT_NUMBER = "idea.launcher.port";
|
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";
|
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 final String LAUNCHER_MAIN_CLASS = "idea.launcher.main.class";
|
||||||
|
|
||||||
private static native void triggerControlBreak();
|
private static void startMonitor(final int portNumber) {
|
||||||
|
|
||||||
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) {
|
|
||||||
Thread t = new Thread("Monitor Ctrl-Break") {
|
Thread t = new Thread("Monitor Ctrl-Break") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try (
|
||||||
try (Socket client = new Socket("127.0.0.1", portNumber)) {
|
Socket client = new Socket("127.0.0.1", portNumber);
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII"))) {
|
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII"))
|
||||||
|
) {
|
||||||
while (true) {
|
while (true) {
|
||||||
String msg = reader.readLine();
|
String msg = reader.readLine();
|
||||||
if (msg == null || "TERM".equals(msg)) {
|
if (msg == null || "TERM".equals(msg)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ("BREAK".equals(msg)) {
|
|
||||||
if (helperLibLoaded) {
|
|
||||||
triggerControlBreak();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ("STOP".equals(msg)) {
|
else if ("STOP".equals(msg)) {
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ignored) { }
|
catch (Exception ignored) { }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -77,9 +46,8 @@ public final class AppMainV2 {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
try {
|
try {
|
||||||
boolean helperLibLoaded = loadHelper(System.getProperty(LAUNCHER_BIN_PATH));
|
|
||||||
int portNumber = Integer.parseInt(System.getProperty(LAUNCHER_PORT_NUMBER));
|
int portNumber = Integer.parseInt(System.getProperty(LAUNCHER_PORT_NUMBER));
|
||||||
startMonitor(portNumber, helperLibLoaded);
|
startMonitor(portNumber);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');
|
System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');
|
||||||
@@ -263,10 +231,8 @@ public final class AppMainV2 {
|
|||||||
public static void premain(String args) {
|
public static void premain(String args) {
|
||||||
try {
|
try {
|
||||||
int p = args.indexOf(':');
|
int p = args.indexOf(':');
|
||||||
if (p < 0) throw new IllegalArgumentException("incorrect parameter: " + args);
|
int portNumber = Integer.parseInt(p > 0 ? args.substring(0, p) : args);
|
||||||
boolean helperLibLoaded = loadHelper(args.substring(p + 1));
|
startMonitor(portNumber);
|
||||||
int portNumber = Integer.parseInt(args.substring(0, p));
|
|
||||||
startMonitor(portNumber, helperLibLoaded);
|
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');
|
System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');
|
||||||
|
|||||||
Reference in New Issue
Block a user