mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-13 06:59:44 +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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ProcessProxyImpl> 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;
|
||||
|
||||
@@ -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() + ')');
|
||||
@@ -263,10 +231,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() + ')');
|
||||
|
||||
Reference in New Issue
Block a user