Ich versuche, ein vorhandenes Java mit Gradle-Projekt zu übernehmen und es Akka-Akteure verwenden zu lassen. Wenn ich ein Akteursystem erstelle, erhalte ich eine Fehlermeldung. Dieser Fehler scheint nur aufzutreten, wenn ich den Code mit Gradle ausführe (aber nicht mit Intelij, dazu später mehr). Der Code erstellt einfach ein neues ActorSystem, wie das Beispiel in der Dokumentation zeigt. Unten finden Sie die gesamte Hauptmethode.
Mein Code
Code: Select all
public final class Main {
private Main() {}
public static void main(String... args) {
var a = ActorSystem.create(Behaviors.logMessages(Behaviors.ignore()), "Machine");
// the code fails on the above line, before anything else can happen
System.out.print("\n".repeat(5));
a.tell("hello");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.print("\n".repeat(5));
a.terminate();
}
}
Wenn ich den obigen Code mit der Ausführungsaufgabe des Projekts ausführe, erhalte ich die folgende Ausgabe und Fehlermeldung.
Code: Select all
[WARN] [01/05/2025 13:14:04.410] [Machine-akka.actor.internal-dispatcher-2] [CoordinatedShutdown(akka://Machine)] Task [terminate-system] in phase [actor-system-terminate] threw an exception before its future could be constructed: actor name [user] is not unique!
Code: Select all
1:30:36 PM: Executing ':frc.robot.Main.main()'…
> Task :eventDeploy
Not running deploy task, skipping commit
> Task :createVersionFile
createVersionFile called. Path /[projectroot]/src/main/java/frc/robot
> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes
warning: Supported source version 'RELEASE_17' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '22'
1 warning
> Task :frc.robot.Main.main()
[2025-01-05 13:30:38,133] [INFO] [akka.event.slf4j.Slf4jLogger] [Machine-akka.actor.default-dispatcher-4] [] - Slf4jLogger started
[2025-01-05 13:30:38,139] [WARN] [akka.actor.ActorSystemImpl] [Machine-akka.actor.default-dispatcher-4] [akka.actor.ActorSystemImpl(Machine)] - Dev use only. Free keys at https://akka.io/key
[2025-01-05 13:30:38,182] [INFO] [akka.actor.CoordinatedShutdown] [Machine-akka.actor.default-dispatcher-4] [CoordinatedShutdown(akka://Machine)] - Running CoordinatedShutdown with reason [ActorSystemTerminateReason]
[Incubating] Problems report is available at: file:///[projectroot]/build/reports/problems/problems-report.html
BUILD SUCCESSFUL in 1s
5 actionable tasks: 4 executed, 1 up-to-date
1:30:38 PM: Execution finished ':frc.robot.Main.main()'.
Ich vermute, dass dies ein Problem mit dem Gradle-Build-System des Projekts ist, denn wann Ich führe den Code über die Schaltfläche „Ausführen“ von Intelij statt über die Gradle-Aufgabe des Projekts aus. Er läuft einwandfrei und erzeugt die folgende Ausgabe:
Code: Select all
1:54:41 PM: Executing ':frc.robot.Main.main()'…
> Task :eventDeploy
Not running deploy task, skipping commit
> Task :createVersionFile
createVersionFile called. Path /[projectroot]/src/main/java/frc/robot
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :frc.robot.Main.main()
[2025-01-05 13:54:41,812] [INFO] [akka.event.slf4j.Slf4jLogger] [Machine-akka.actor.default-dispatcher-4] [] - Slf4jLogger started
[2025-01-05 13:54:41,818] [WARN] [akka.actor.ActorSystemImpl] [Machine-akka.actor.default-dispatcher-4] [akka.actor.ActorSystemImpl(Machine)] - Dev use only. Free keys at https://akka.io/key
[2025-01-05 13:54:41,861] [INFO] [akka.actor.CoordinatedShutdown] [Machine-akka.actor.default-dispatcher-4] [CoordinatedShutdown(akka://Machine)] - Running CoordinatedShutdown with reason [ActorSystemTerminateReason]
BUILD SUCCESSFUL in 628ms
5 actionable tasks: 3 executed, 2 up-to-date
1:54:41 PM: Execution finished ':frc.robot.Main.main()'.
Gedanken
Ich weiß es nicht Genug über Akka, um zu verstehen, warum es zweimal versucht, Adressen für den Benutzer-Akteur zu reservieren, aber nur in bestimmten Kontexten.
Mein gradle.build
Das Gradle-Projekt ist also ein FRC-Projekt Um es zu reproduzieren, wäre die Installation von WPILIB und ein wenig Mühe erforderlich, daher würde ich nicht empfehlen, es zu reproduzieren, aber wenn Sie möchten, finden Sie hier die Zip-Datei, auf der das Projekt basiert. Unten ist mein build.gradle und hier ist es das WPILIB-Installationsprogramm, das ich verwendet habe. Ich verwende MacOS 15.2.
Code: Select all
import edu.wpi.first.gradlerio.GradleRIOPlugin
plugins {
id "java"
id "idea"
id "application"
id "edu.wpi.first.GradleRIO" version "2025.1.1-beta-2"
id "com.peterabeles.gversion" version "1.10"
// id "com.diffplug.spotless" version "6.12.0"
}
java {
sourceCompatibility = JavaVersion.VERSION_22
targetCompatibility = JavaVersion.VERSION_22
}
def ROBOT_MAIN_CLASS = "frc.robot.Main"
// Define my targets (RoboRIO) and artifacts (deployable files)
// This is added by GradleRIO's backing project DeployUtils.
deploy {
targets {
roborio(getTargetTypeClass('RoboRIO')) {
// Team number is loaded either from the .wpilib/wpilib_preferences.json
// or from command line. If not found an exception will be thrown.
// You can use getTeamOrDefault(team) instead of getTeamNumber if you
// want to store a team number in this file.
team = project.frc.getTeamNumber()
debug = project.frc.getDebugOrDefault(false)
artifacts {
// First part is artifact name, 2nd is artifact type
// getTargetTypeClass is a shortcut to get the class type using a string
frcJava(getArtifactTypeClass('FRCJavaArtifact')) {
jvmArgs.add("-XX:+UnlockExperimentalVMOptions")
jvmArgs.add("-XX:GCTimeRatio=5")
jvmArgs.add("-XX:+UseSerialGC")
jvmArgs.add("-XX:MaxGCPauseMillis=50")
// The options below may improve performance, but should only be enabled on the RIO 2
//
// final MAX_JAVA_HEAP_SIZE_MB = 100;
// jvmArgs.add("-Xmx" + MAX_JAVA_HEAP_SIZE_MB + "M")
// jvmArgs.add("-Xms" + MAX_JAVA_HEAP_SIZE_MB + "M")
// jvmArgs.add("-XX:+AlwaysPreTouch")
}
// Static files artifact
frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) {
files = project.fileTree('src/main/deploy')
directory = '/home/lvuser/deploy'
// Change to true to delete files on roboRIO that no
// longer exist in deploy directory on roboRIO
deleteOldFiles = false
}
}
}
}
}
def deployArtifact = deploy.targets.roborio.artifacts.frcJava
// Set to true to use debug for JNI.
wpi.java.debugJni = false
// Set this to true to enable desktop support.
def includeDesktopSupport = true
// Configuration for AdvantageKit
repositories {
maven {
url = uri("https://maven.pkg.github.com/Mechanical-Advantage/AdvantageKit")
credentials {
username = "Mechanical-Advantage-Bot"
password = "\u0067\u0068\u0070\u005f\u006e\u0056\u0051\u006a\u0055\u004f\u004c\u0061\u0079\u0066\u006e\u0078\u006e\u0037\u0051\u0049\u0054\u0042\u0032\u004c\u004a\u006d\u0055\u0070\u0073\u0031\u006d\u0037\u004c\u005a\u0030\u0076\u0062\u0070\u0063\u0051"
}
}
maven {
url "https://repo.akka.io/maven"
}
mavenCentral()
mavenLocal()
}
task(replayWatch, type: JavaExec) {
mainClass = "org.littletonrobotics.junction.ReplayWatch"
classpath = sourceSets.main.runtimeClasspath
}
def versions = [
ScalaBinary: "2.13"
]
// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries.
// Also defines JUnit 4.
dependencies {
annotationProcessor wpi.java.deps.wpilibAnnotations()
implementation wpi.java.deps.wpilib()
implementation wpi.java.vendor.java()
roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio)
roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio)
roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio)
roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio)
nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
simulationDebug wpi.sim.enableDebug()
nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
simulationRelease wpi.sim.enableRelease()
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text)
annotationProcessor "org.littletonrobotics.akit:akit-autolog:$akitJson.version"
implementation platform("com.typesafe.akka:akka-bom_${versions.ScalaBinary}:2.10.0")
implementation "com.typesafe.akka:akka-actor-typed_${versions.ScalaBinary}"
testImplementation "com.typesafe.akka:akka-actor-testkit-typed_${versions.ScalaBinary}"
annotationProcessor "org.jetbrains:annotations:24.0.0"
implementation "org.jetbrains:annotations:24.0.0"
implementation "ch.qos.logback:logback-classic:1.5.6"
}
test {
useJUnitPlatform()
systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true'
}
// Simulation configuration (e.g. environment variables).
//
// The sim GUI is *disabled* by default to support running
// AdvantageKit log replay from the command line. Set the
// value to "true" to enable the sim GUI by default (this
// is the standard WPILib behavior).
wpi.sim.addGui().defaultEnabled = true
wpi.sim.addDriverstation()
// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar')
// in order to make them all available at runtime. Also adding the manifest so WPILib
// knows where to look for our Robot Class.
jar {
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
from sourceSets.main.allSource
manifest GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
// Configure jar and deploy tasks
deployArtifact.jarTask = jar
wpi.java.configureExecutableTasks(jar)
wpi.java.configureTestTasks(test)
// Configure string concat to always inline compile
tasks.withType(JavaCompile) {
options.compilerArgs.add '-XDstringConcat=inline'
}
// Create version file
project.compileJava.dependsOn(createVersionFile)
gversion {
srcDir = "src/main/java/"
classPackage = "frc.robot"
className = "BuildConstants"
dateFormat = "yyyy-MM-dd HH:mm:ss z"
timeZone = "America/New_York"
indent = " "
}
// Create commit with working changes on event branches
task(eventDeploy) {
doLast {
if (project.gradle.startParameter.taskNames.any({ it.toLowerCase().contains("deploy") })) {
def branchPrefix = "event"
def branch = 'git branch --show-current'.execute().text.trim()
def commitMessage = "Update at '${new Date().toString()}'"
if (branch.startsWith(branchPrefix)) {
exec {
workingDir(projectDir)
executable 'git'
args 'add', '-A'
}
exec {
workingDir(projectDir)
executable 'git'
args 'commit', '-m', commitMessage
ignoreExitValue = true
}
println "Committed to branch: '$branch'"
println "Commit message: '$commitMessage'"
} else {
println "Not on an event branch, skipping commit"
}
} else {
println "Not running deploy task, skipping commit"
}
}
}
createVersionFile.dependsOn(eventDeploy)
//// Spotless formatting
//project.compileJava.dependsOn(spotlessApply)
//spotless {
// java {
// target fileTree(".") {
// include "**/*.java"
// exclude "**/build/**", "**/build-*/**"
// }
// toggleOffOn()
// googleJavaFormat()
// removeUnusedImports()
// trimTrailingWhitespace()
// endWithNewline()
// }
// groovyGradle {
// target fileTree(".") {
// include "**/*.gradle"
// exclude "**/build/**", "**/build-*/**"
// }
// greclipse()
// indentWithSpaces(4)
// trimTrailingWhitespace()
// endWithNewline()
// }
// json {
// target fileTree(".") {
// include "**/*.json"
// exclude "**/build/**", "**/build-*/**"
// }
// gson().indentWithSpaces(2)
// }
// format "misc", {
// target fileTree(".") {
// include "**/*.md", "**/.gitignore"
// exclude "**/build/**", "**/build-*/**"
// }
// trimTrailingWhitespace()
// indentWithSpaces(2)
// endWithNewline()
// }
//}
Ich habe bei Google nachgesehen und es gibt viele Threads, in denen es um doppelte Schauspieler geht, aber keinen über ActorSystem.create(... ) schlägt fehl, da versucht wird, mehrere Benutzer-Akteure zu erstellen.
Was ich versucht habe
Ich habe versucht
- unter Verwendung der empfohlenen Version und Distribution von Java, verschiedene Versionen
Hinzufügen ihrer Standardanwendung.conf zum Ressourcenordner (was anscheinend funktioniert, denn als ich das falsch gemacht habe, hat es einen neuen Fehler ausgelöst).
Ich habe einfach nicht genug Erfahrung mit Akka, um diesen Fehler zu erkennen oder zu verstehen irgendetwas darüber, was es verursachen könnte.
Meine Frage
Was könnte dieses Problem verursachen? Mir ist klar, dass es schwierig ist, dies zu diagnostizieren, wenn es nicht viel gibt, mit dem man arbeiten kann, aber ich brauche nur Hinweise darauf, was die Ursache sein könnte. Sobald ich den konkreten Unterschied zwischen den beiden Ausführungsarten verstehe, kann ich Dinge ändern, damit es funktioniert.