Skip to content

Commit 3ffa4ed

Browse files
JaroslavTulachFrizi
authored andcommitted
Handle --jvm flag in process with JNI instantiated JVM (#12843)
Fixes #12842 by designing a _JNI OS environment_, providing its implementations for supported platforms and using it to handle `--jvm` flag. All the _Standard Library Tests (jvm)_ use this new launch-in-the-same-process technique.
1 parent 07184a8 commit 3ffa4ed

File tree

35 files changed

+4124
-178
lines changed

35 files changed

+4124
-178
lines changed

build.sbt

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ lazy val enso = (project in file("."))
363363
`persistance`,
364364
`persistance-dsl`,
365365
pkg,
366+
`poi-wrapper`,
366367
`polyglot-api`,
367368
`polyglot-api-macros`,
368369
`process-utils`,
@@ -618,7 +619,7 @@ val bouncyCastle = Seq(
618619
val jlineVersion = "3.26.3"
619620
val jline = Seq(
620621
"org.jline" % "jline-terminal" % jlineVersion,
621-
"org.jline" % "jline-terminal-jna" % jlineVersion,
622+
"org.jline" % "jline-terminal-jni" % jlineVersion, // The terminal provider jna has been deprecated, check your configuration.
622623
"org.jline" % "jline-reader" % jlineVersion,
623624
"org.jline" % "jline-native" % jlineVersion
624625
)
@@ -1384,6 +1385,20 @@ lazy val `jna-wrapper` = project
13841385
}
13851386
)
13861387

1388+
lazy val `poi-wrapper` = project
1389+
.in(file("lib/java/poi-wrapper"))
1390+
.settings(
1391+
frgaalJavaCompilerSetting,
1392+
version := "0.1",
1393+
autoScalaLibrary := false,
1394+
libraryDependencies ++= Seq(
1395+
"org.apache.poi" % "poi-ooxml" % poiOoxmlVersion
1396+
),
1397+
assemblyMergeStrategy := { case _ =>
1398+
MergeStrategy.preferProject
1399+
}
1400+
)
1401+
13871402
lazy val `runtime-utils` = project
13881403
.in(file("lib/java/runtime-utils"))
13891404
.enablePlugins(JPMSPlugin)
@@ -1435,6 +1450,7 @@ lazy val `directory-watcher-wrapper` = project
14351450
)
14361451
}
14371452
)
1453+
.dependsOn(`jna-wrapper` % "provided")
14381454

14391455
lazy val `fansi-wrapper` = project
14401456
.in(file("lib/java/fansi-wrapper"))
@@ -1495,14 +1511,16 @@ lazy val `akka-wrapper` = project
14951511
"com.google.protobuf" % "protobuf-java" % googleProtobufVersion,
14961512
"io.github.java-diff-utils" % "java-diff-utils" % javaDiffVersion,
14971513
"org.reactivestreams" % "reactive-streams" % reactiveStreamsVersion,
1498-
"net.java.dev.jna" % "jna" % jnaVersion,
14991514
"io.spray" %% "spray-json" % sprayJsonVersion
15001515
),
15011516
javaModuleName := "org.enso.akka.wrapper",
15021517
Compile / moduleDependencies ++= slf4jApi ++ Seq(
15031518
"com.google.protobuf" % "protobuf-java" % googleProtobufVersion,
15041519
"org.reactivestreams" % "reactive-streams" % reactiveStreamsVersion
15051520
),
1521+
Compile / internalModuleDependencies := Seq(
1522+
(`jna-wrapper` / Compile / exportedModule).value
1523+
),
15061524
assembly / assemblyExcludedJars := {
15071525
val excludedJars = JPMSUtils.filterModulesFromUpdate(
15081526
update.value,
@@ -1511,8 +1529,7 @@ lazy val `akka-wrapper` = project
15111529
"com.typesafe" % "config" % typesafeConfigVersion,
15121530
"io.github.java-diff-utils" % "java-diff-utils" % javaDiffVersion,
15131531
"com.google.protobuf" % "protobuf-java" % googleProtobufVersion,
1514-
"org.reactivestreams" % "reactive-streams" % reactiveStreamsVersion,
1515-
"net.java.dev.jna" % "jna" % jnaVersion
1532+
"org.reactivestreams" % "reactive-streams" % reactiveStreamsVersion
15161533
),
15171534
streams.value.log,
15181535
moduleName.value,
@@ -1549,6 +1566,7 @@ lazy val `akka-wrapper` = project
15491566
)
15501567
}
15511568
)
1569+
.dependsOn(`jna-wrapper` % "provided")
15521570

15531571
lazy val `zio-wrapper` = project
15541572
.in(file("lib/java/zio-wrapper"))
@@ -3902,7 +3920,7 @@ lazy val `engine-runner` = project
39023920
val NI_MODULES =
39033921
"org.graalvm.nativeimage,org.graalvm.nativeimage.builder,org.graalvm.nativeimage.base,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.objectfile,org.graalvm.nativeimage.pointsto,com.oracle.graal.graal_enterprise,com.oracle.svm.svm_enterprise"
39043922
val JDK_MODULES =
3905-
"java.desktop,java.naming,java.net.http,jdk.charsets,jdk.crypto.ec,jdk.localedata,jdk.httpserver,java.rmi"
3923+
"java.naming,java.net.http,jdk.charsets,jdk.crypto.ec,jdk.localedata,jdk.httpserver,java.rmi"
39063924
val DEBUG_MODULES = "jdk.jdwp.agent"
39073925
val PYTHON_MODULES = "jdk.security.auth,java.naming"
39083926

@@ -3982,6 +4000,7 @@ lazy val `engine-runner` = project
39824000
"-H:+AddAllCharsets",
39834001
"-H:+IncludeAllLocales",
39844002
"-H:+RunReachabilityHandlersConcurrently",
4003+
"-R:-InstallSegfaultHandler",
39854004
// Workaround a problem with build-/runtime-initialization conflict
39864005
// by disabling this service provider
39874006
"-H:ServiceLoaderFeatureExcludeServiceProviders=net.snowflake.client.core.FileTypeDetector",
@@ -4285,12 +4304,13 @@ lazy val `os-environment` =
42854304
val targetDir = (Test / target).value
42864305
NativeImage.buildNativeImage(
42874306
"test-os-env",
4288-
staticOnLinux = true,
4307+
staticOnLinux = false,
42894308
targetDir = targetDir,
42904309
mainClass = Some("org.enso.os.environment.TestRunner"),
42914310
additionalOptions = Seq(
42924311
"-ea",
4293-
"--features=org.enso.os.environment.TestCollectorFeature"
4312+
"--features=org.enso.os.environment.TestCollectorFeature",
4313+
"-R:-InstallSegfaultHandler"
42944314
)
42954315
)
42964316
}.value,
@@ -4301,7 +4321,7 @@ lazy val `os-environment` =
43014321
val exeFile =
43024322
(Test / target).value / ("test-os-env" + exeSuffix)
43034323
val binPath = exeFile.getAbsolutePath
4304-
val res = binPath ! logger
4324+
val res = Process(Seq(binPath), None, "JAVA_OPTS" -> "") ! logger
43054325
if (res != 0) {
43064326
logger.error("Some test in os-environment failed")
43074327
throw new TestsFailedException()
@@ -5027,6 +5047,11 @@ lazy val `std-table` = project
50275047
"org.mockito" % "mockito-core" % mockitoJavaVersion % Test,
50285048
"org.mockito" % "mockito-junit-jupiter" % mockitoJavaVersion % Test
50295049
),
5050+
Compile / unmanagedJars := {
5051+
Seq(
5052+
Attributed.blank((`poi-wrapper` / assembly).value)
5053+
)
5054+
},
50305055
Compile / packageBin := {
50315056
val result = (Compile / packageBin).value
50325057
val cacheStoreFactory = streams.value.cacheStoreFactory
@@ -5037,13 +5062,21 @@ lazy val `std-table` = project
50375062
ignoreScalaLibrary = true,
50385063
libraryUpdates = (Compile / update).value,
50395064
unmanagedClasspath = (Compile / unmanagedJars).value,
5040-
logger = streams.value.log,
5041-
cacheStoreFactory = cacheStoreFactory,
5042-
previousRun = None
5065+
ignoreDependencies = Some(
5066+
Seq(
5067+
"org.apache.poi" % "poi" % poiOoxmlVersion,
5068+
"org.apache.poi" % "poi-ooxml" % poiOoxmlVersion,
5069+
"org.apache.poi" % "poi-ooxml-lite" % poiOoxmlVersion
5070+
)
5071+
),
5072+
logger = streams.value.log,
5073+
cacheStoreFactory = cacheStoreFactory,
5074+
previousRun = None
50435075
)
50445076
result
50455077
}
50465078
)
5079+
.dependsOn(`poi-wrapper`)
50475080
.dependsOn(`std-base` % "provided")
50485081

50495082
lazy val extractNativeLibs = taskKey[AnalysisOfExtractedNativeLibs](
@@ -5082,7 +5115,8 @@ lazy val `std-image` = project
50825115
`image-polyglot-root`,
50835116
Seq("std-image.jar", "opencv.jar"),
50845117
ignoreScalaLibrary = true,
5085-
ignoreDependency = Some("org.openpnp" % "opencv" % opencvVersion),
5118+
ignoreDependencies =
5119+
Some(Seq("org.openpnp" % "opencv" % opencvVersion)),
50865120
libraryUpdates = (Compile / update).value,
50875121
logger = logger,
50885122
cacheStoreFactory = cacheStoreFactory,
@@ -5515,7 +5549,6 @@ lazy val `std-tableau` = project
55155549
unmanagedClasspath = unmanagedClasspath,
55165550
previousRun = prev
55175551
)
5518-
55195552
StdBits
55205553
.extractNativeLibsFromTableau(
55215554
`std-tableau-polyglot-root`,

distribution/engine/THIRD-PARTY/NOTICE

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,6 @@ The license file can be found at `licenses/APACHE2.0`.
361361
Copyright notices related to this dependency can be found in the directory `jakarta.inject.jakarta.inject-api-2.0.1`.
362362

363363

364-
'jna', licensed under the Apache-2.0, is distributed with the engine.
365-
The license file can be found at `licenses/APACHE2.0`.
366-
Copyright notices related to this dependency can be found in the directory `net.java.dev.jna.jna-5.14.0`.
367-
368-
369364
'commons-compress', licensed under the Apache-2.0, is distributed with the engine.
370365
The license file can be found at `licenses/APACHE2.0`.
371366
Copyright notices related to this dependency can be found in the directory `org.apache.commons.commons-compress-1.23.0`.
@@ -531,9 +526,9 @@ The license file can be found at `licenses/BSD-3-Clause`.
531526
Copyright notices related to this dependency can be found in the directory `org.jline.jline-terminal-3.26.3`.
532527

533528

534-
'jline-terminal-jna', licensed under the The BSD License, is distributed with the engine.
529+
'jline-terminal-jni', licensed under the The BSD License, is distributed with the engine.
535530
The license file can be found at `licenses/BSD-3-Clause`.
536-
Copyright notices related to this dependency can be found in the directory `org.jline.jline-terminal-jna-3.26.3`.
531+
Copyright notices related to this dependency can be found in the directory `org.jline.jline-terminal-jni-3.26.3`.
537532

538533

539534
'org-netbeans-modules-sampler', licensed under the The Apache Software License, Version 2.0, is distributed with the engine.

distribution/engine/THIRD-PARTY/net.java.dev.jna.jna-5.14.0/NOTICES

Lines changed: 0 additions & 29 deletions
This file was deleted.

distribution/engine/THIRD-PARTY/org.jline.jline-terminal-jna-3.26.3/NOTICES

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Copyright (C) 2022 the original author(s).
2+
3+
Copyright (c) 2002-2017, the original author(s).
4+
5+
Copyright (c) 2002-2020, the original author or authors.
6+
7+
Copyright (c) 2002-2020, the original author(s).
8+
9+
Copyright (c) 2009-2018, the original author(s).

engine/runner/src/main/java/org/enso/runner/JavaFinder.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.enso.runner;
22

3+
import java.io.File;
34
import java.io.IOException;
45
import java.nio.file.Path;
56
import java.util.Comparator;
@@ -27,10 +28,10 @@ private JavaFinder() {}
2728
* @return null if cannot be found. Otherwise, returns the absolute path to the executable, or
2829
* simply {@code java} if it is on the {@code PATH}.
2930
*/
30-
static String findJavaExecutable() {
31+
static File findJavaExecutable() {
3132
var javaInRuntime = findJavaExecutableInDistributionRuntimes();
3233
if (javaInRuntime != null) {
33-
return javaInRuntime.toAbsolutePath().toString();
34+
return javaInRuntime.toAbsolutePath().toFile();
3435
}
3536
logger.warn("No appropriate JDK found in the distribution runtimes. Trying system-wide JDK.");
3637
var javaHome = System.getenv("JAVA_HOME");
@@ -44,7 +45,7 @@ static String findJavaExecutable() {
4445
}
4546
if (javaExe.toFile().exists()) {
4647
logger.info("Found JDK in JAVA_HOME: {}", javaHome);
47-
return javaExe.toAbsolutePath().toString();
48+
return javaExe.toAbsolutePath().toFile();
4849
} else {
4950
logger.warn(
5051
"No JDK found in JAVA_HOME (missing Java executable at {}). Trying java on PATH.",
@@ -54,10 +55,9 @@ static String findJavaExecutable() {
5455
logger.warn("JAVA_HOME is not set. Trying java on PATH.");
5556
}
5657

57-
if (isJavaOnPath()) {
58-
var javaExe = isOnWindows() ? "java.exe" : "java";
59-
logger.warn("Falling back to java on PATH: {}", javaExe);
60-
return javaExe;
58+
if (findJavaOnPath() instanceof File javaExecutable) {
59+
logger.warn("Falling back to java on PATH: {}", javaExecutable);
60+
return javaExecutable;
6161
}
6262
logger.warn("No JDK found on PATH. Cannot start the runtime.");
6363
return null;
@@ -107,7 +107,7 @@ private static Path findJavaExecutableInDistributionRuntimes() {
107107
return null;
108108
}
109109

110-
private static boolean isJavaOnPath() {
110+
private static File findJavaOnPath() {
111111
try {
112112
ProcessBuilder processBuilder;
113113
if (isOnWindows()) {
@@ -116,10 +116,11 @@ private static boolean isJavaOnPath() {
116116
processBuilder = new ProcessBuilder("java", "-h");
117117
}
118118
Process process = processBuilder.start();
119+
var pathOpt = process.info().command();
119120
boolean exitSucc = process.waitFor(5L, TimeUnit.SECONDS);
120-
return exitSucc;
121+
return exitSucc && pathOpt.isPresent() ? new File(pathOpt.get()) : null;
121122
} catch (IOException | InterruptedException e) {
122-
return false;
123+
return null;
123124
}
124125
}
125126
}

0 commit comments

Comments
 (0)