Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/aot-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ jobs:
# See if it runs at all
target/graalvm-native-image/jelly-cli version

# Make sure reflection works
# Make sure reflection is supported
target/graalvm-native-image/jelly-cli version | grep "JVM reflection: supported"

# Make sure large RDF/XML file parsing is supported
target/graalvm-native-image/jelly-cli version | grep "Large RDF/XML file parsing: supported"

# Test RDF conversions
echo '_:b <http://t.org/> _:b .' > in.nt
target/graalvm-native-image/jelly-cli \
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/scala.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ jobs:
java: 17
- os: ubuntu-latest
java: 21
- os: ubuntu-latest
java: 24
runs-on: ${{ matrix.os }}

steps:
Expand Down
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ lazy val graalOptions = Seq(
if (isDevBuild) Seq("-Ob") else Seq("-O3", "--emit build-report"),
).flatten ++ Seq(
"--features=eu.neverblink.jelly.cli.graal.ProtobufFeature," +
"eu.neverblink.jelly.cli.graal.JenaInternalsFeature",
"eu.neverblink.jelly.cli.graal.JenaInternalsFeature," +
"eu.neverblink.jelly.cli.graal.LargeXmlFeature",
"-H:ReflectionConfigurationFiles=" + file("graal.json").getAbsolutePath,
// Needed to skip initializing all charsets.
// See: https://github.com/Jelly-RDF/cli/issues/154
Expand Down
56 changes: 44 additions & 12 deletions src/main/scala/eu/neverblink/jelly/cli/command/Version.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,18 @@ object Version extends JellyCommand[VersionOptions]:
.find(_.startsWith("org.apache.jena:jena-core:")).get.split(":")(2)
val jellyV = BuildInfo.libraryDependencies
.find(_.startsWith("eu.neverblink.jelly:jelly-jena:")).get.split(":")(2)
val reflectionSupported = JenaSystemOptions.disableTermValidation()

printLine(f"""
|jelly-cli ${BuildInfo.version}
|----------------------------------------------
|-------------------------------------------------------------
|Jelly-JVM $jellyV
|Apache Jena $jenaV
|JVM ${System.getProperty("java.vm.name")} ${System.getProperty("java.vm.version")}
|----------------------------------------------
|-------------------------------------------------------------
|""".stripMargin.trim)
// Print feature support info
reflectionSupported match {
case Failure(ex) =>
printLine("[ ] JVM reflection: not supported. Parsing will be slower.")
if getOptions.common.debug then
printLine(" The exception was:")
ex.printStackTrace(out)
else printLine(" Run with --debug for details.")
case Success(_) => printLine("[X] JVM reflection: supported. Parsing optimizations enabled.")
}
printReflectionSupport()
printLargeXmlParsingSupport()
// Print copyright info
val buildYear = new SimpleDateFormat("yyyy").format(Date(BuildInfo.buildTime))
printLine(f"""
Expand All @@ -57,3 +50,42 @@ object Version extends JellyCommand[VersionOptions]:
|This software comes with no warranties and is provided 'as-is'.
|Documentation and author list: https://github.com/Jelly-RDF/cli
""".stripMargin)

private def printReflectionSupport(): Unit =
val reflectionSupported = JenaSystemOptions.disableTermValidation()
reflectionSupported match {
case Failure(ex) =>
printLine("[ ] JVM reflection: not supported. Parsing will be slower.")
if getOptions.common.debug then
printLine(" The exception was:")
ex.printStackTrace(out)
else printLine(" Run with --debug for details.")
case Success(_) => printLine("[X] JVM reflection: supported. Parsing optimizations enabled.")
}

private def printLargeXmlParsingSupport(): Unit =
// See: https://github.com/Jelly-RDF/cli/issues/220
val maxGeneralEntitySizeLimit = System.getProperty("jdk.xml.maxGeneralEntitySizeLimit")
val totalEntitySizeLimit = System.getProperty("jdk.xml.totalEntitySizeLimit")
val ok =
if Runtime.version().feature() <= 23 then
// JDK 23 and earlier did not have the new limits, so large XML files are always supported.
true
// 50M was the default totalEntitySizeLimit in JDK 23 and earlier.
// maxGeneralEntitySizeLimit was not defined (0) in JDK 23 and earlier.
else if maxGeneralEntitySizeLimit != null && maxGeneralEntitySizeLimit.toLong <= 0 &&
totalEntitySizeLimit != null && (totalEntitySizeLimit.toLong <= 0 || totalEntitySizeLimit.toLong >= 50_000_000)
then true
else false

if ok
then printLine("[X] Large RDF/XML file parsing: supported.")
else
printLine("[ ] Large RDF/XML file parsing: not supported.")
if getOptions.common.debug then
printLine(
f" jdk.xml.maxGeneralEntitySizeLimit = $maxGeneralEntitySizeLimit",
)
printLine(f" jdk.xml.totalEntitySizeLimit = $totalEntitySizeLimit")
printLine(" To enable large XML parsing, set both properties to 0 (no limit).")
else printLine(" Run with --debug for details.")
16 changes: 16 additions & 0 deletions src/main/scala/eu/neverblink/jelly/cli/graal/LargeXmlFeature.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package eu.neverblink.jelly.cli.graal

import org.graalvm.nativeimage.hosted.{Feature, RuntimeSystemProperties}

class LargeXmlFeature extends Feature:
import Feature.*

override def getDescription: String =
"Increases XML parsing limits to support large RDF/XML files."

override def beforeAnalysis(access: BeforeAnalysisAccess): Unit =
// Support arbitrarily large RDF/XML files – needed since JDK 24.
// 0 indicates no limit.
// Issue: https://github.com/Jelly-RDF/cli/issues/220
RuntimeSystemProperties.register("jdk.xml.maxGeneralEntitySizeLimit", "0")
RuntimeSystemProperties.register("jdk.xml.totalEntitySizeLimit", "0")
12 changes: 12 additions & 0 deletions src/test/scala/eu/neverblink/jelly/cli/command/VersionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ class VersionSpec extends AnyWordSpec, Matchers:
out should include("[X] JVM reflection: supported.")
}

"report that large XML parsing is supported by default if running under JVM <= 23" in {
assume(Runtime.version().feature() <= 23, "Test only valid for JVM <= 23")
val (out, err) = Version.runTestCommand(List(alias))
out should include("[X] Large RDF/XML file parsing: supported.")
}

"report that large XML parsing is not supported by default if running under JVM >= 24" in {
assume(Runtime.version().feature() >= 24, "Test only valid for JVM >= 24")
val (out, err) = Version.runTestCommand(List(alias))
out should include("[ ] Large RDF/XML file parsing: not supported.")
}

"include the copyright year" in {
val (out, err) = Version.runTestCommand(List(alias))
val currentYear = java.time.Year.now.getValue.toString
Expand Down