Skip to content

修复 GameAdvancedListItem#loadVersion UI 操作可能不会 JavaFX 线程运行的问题#6445

Merged
Glavo merged 6 commits into
HMCL-dev:mainfrom
CiiLu:fffffx
Jul 22, 2026
Merged

修复 GameAdvancedListItem#loadVersion UI 操作可能不会 JavaFX 线程运行的问题#6445
Glavo merged 6 commits into
HMCL-dev:mainfrom
CiiLu:fffffx

Conversation

@CiiLu

@CiiLu CiiLu commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

resolves #6443
附来自崩溃群 & 用户群的完整报告

---- Hello Minecraft! Crash Report ----
  Version: 3.16.2
  Time: 2026-07-20 16:08:24
  Thread: Thread[#47,ForkJoinPool.commonPool-worker-3,5,InnocuousForkJoinWorkerThreadGroup]

  Content: 
    java.lang.IllegalStateException: Not on FX application thread; currentThread = ForkJoinPool.commonPool-worker-3
	at javafx.graphics@25/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:282)
	at javafx.graphics@25/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:475)
	at javafx.graphics@25/javafx.scene.Parent$3.onProposedChange(Parent.java:539)
	at javafx.base@25/com.sun.javafx.collections.VetoableListDecorator.setAllImpl(VetoableListDecorator.java:127)
	at javafx.base@25/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:118)
	at javafx.controls@25/javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:285)
	at javafx.controls@25/javafx.scene.control.skin.LabeledSkinBase.lambda$new$11(LabeledSkinBase.java:222)
	at javafx.controls@25/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$0(LambdaMultiplePropertyChangeListenerHandler.java:88)
	at javafx.base@25/javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:86)
	at javafx.base@25/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:192)
	at javafx.base@25/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
	at javafx.base@25/javafx.beans.property.StringProperty.setValue(StringProperty.java:71)
	at javafx.controls@25/javafx.scene.control.Labeled.setText(Labeled.java:157)
	at org.jackhuang.hmcl.ui.construct.TwoLineListItem$1.invalidated(TwoLineListItem.java:85)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
	at javafx.base@25/javafx.beans.property.StringPropertyBase$Listener.invalidated(StringPropertyBase.java:231)
	at javafx.base@25/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:147)
	at javafx.base@25/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
	at javafx.base@25/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
	at org.jackhuang.hmcl.ui.construct.AdvancedListItem.setTitle(AdvancedListItem.java:107)
	at org.jackhuang.hmcl.ui.versions.GameAdvancedListItem.loadVersion(GameAdvancedListItem.java:72)
	at org.jackhuang.hmcl.ui.versions.GameAdvancedListItem.lambda$loadVersion$2(GameAdvancedListItem.java:67)
	at org.jackhuang.hmcl.event.EventManager.fireEvent(EventManager.java:83)
	at org.jackhuang.hmcl.event.EventBus.fireEvent(EventBus.java:46)
	at org.jackhuang.hmcl.game.DefaultGameRepository.refreshVersions(DefaultGameRepository.java:401)
	at org.jackhuang.hmcl.util.function.ExceptionalRunnable.lambda$toCallable$0(ExceptionalRunnable.java:32)
	at org.jackhuang.hmcl.task.Task$SimpleTask.execute(Task.java:1110)
	at org.jackhuang.hmcl.task.AsyncTaskExecutor.lambda$executeNormalTask$22(AsyncTaskExecutor.java:241)
	at org.jackhuang.hmcl.util.Lang.lambda$wrap$2(Lang.java:303)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1825)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1817)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)


-- System Details --
  Operating System: Windows NT (unknown) 6.1.7601
  System Architecture: x86-64
  Java Architecture: x86-64
  Java Version: 25.0.3, Microsoft
  Java VM Version: OpenJDK 64-Bit Server VM (mixed mode, sharing), Microsoft
  JVM Max Memory: 1073741824
  JVM Total Memory: 76546048
  JVM Free Memory: 43667776
---- Hello Minecraft! Crash Report ----
  Version: 3.17.0.351
  Time: 2026-07-19 09:53:47
  Thread: Thread[#67,ForkJoinPool.commonPool-worker-4,5,InnocuousForkJoinWorkerThreadGroup]

  Content: 
    java.lang.IllegalStateException: Not on FX application thread; currentThread = ForkJoinPool.commonPool-worker-4
    at javafx.graphics@25/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:282)
    at javafx.graphics@25/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:475)
    at javafx.graphics@25/javafx.scene.Parent$3.onProposedChange(Parent.java:539)
    at javafx.base@25/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:221)
    at org.jackhuang.hmcl.ui.construct.TwoLineListItem$2.invalidated(TwoLineListItem.java:125)
    at javafx.base@25/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
    at javafx.base@25/javafx.beans.property.StringPropertyBase$Listener.invalidated(StringPropertyBase.java:231)
    at javafx.base@25/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:147)
    at javafx.base@25/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
    at javafx.base@25/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
    at javafx.base@25/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
    at javafx.base@25/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
    at javafx.base@25/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
    at org.jackhuang.hmcl.ui.construct.AdvancedListItem.setSubtitle(AdvancedListItem.java:121)
    at org.jackhuang.hmcl.ui.versions.GameAdvancedListItem.loadVersion(GameAdvancedListItem.java:73)
    at org.jackhuang.hmcl.ui.versions.GameAdvancedListItem.lambda$loadVersion$2(GameAdvancedListItem.java:67)
    at org.jackhuang.hmcl.event.EventManager.fireEvent(EventManager.java:83)
    at org.jackhuang.hmcl.event.EventBus.fireEvent(EventBus.java:46)
    at org.jackhuang.hmcl.game.DefaultGameRepository.refreshVersions(DefaultGameRepository.java:401)
    at org.jackhuang.hmcl.util.function.ExceptionalRunnable.lambda$toCallable$0(ExceptionalRunnable.java:32)
    at org.jackhuang.hmcl.task.Task$SimpleTask.execute(Task.java:1110)
    at org.jackhuang.hmcl.task.AsyncTaskExecutor.lambda$executeNormalTask$22(AsyncTaskExecutor.java:241)
    at org.jackhuang.hmcl.util.Lang.lambda$wrap$2(Lang.java:303)
    at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1825)
    at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1817)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)


-- System Details --
  Operating System: Windows 11 25H2 10.0.26200.8875
  System Architecture: x86-64
  Java Architecture: x86-64
  Java Version: 25.0.3, Microsoft
  Java VM Version: OpenJDK 64-Bit Server VM (mixed mode, sharing), Microsoft
  JVM Max Memory: 1073741824
  JVM Total Memory: 286261248
  JVM Free Memory: 128702656这是怎么回事?

@github-actions github-actions Bot added the 10+ label Jul 20, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request wraps the UI update logic in GameAdvancedListItem.loadVersion() inside Platform.runLater to ensure it runs on the JavaFX Application Thread. The reviewer suggests using the project's utility method FXUtils.runInFX instead of Platform.runLater to avoid unnecessary thread dispatching when already on the FX thread, which also eliminates the need for the new import. Additionally, the reviewer points out potential concurrency issues with the rest of the method that is still executed outside the FX thread.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java Outdated
@github-actions github-actions Bot added 40+ and removed 10+ labels Jul 20, 2026
@Glavo

Glavo commented Jul 20, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 73b20ce3d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java Outdated
@github-actions github-actions Bot added 10+ and removed 40+ labels Jul 20, 2026
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameAdvancedListItem.java Outdated
@github-actions github-actions Bot added 1+ and removed 10+ labels Jul 21, 2026
setLeftGraphic(imageContainer);

holder.add(FXUtils.onWeakChangeAndOperate(GameDirectoryManager.selectedInstanceProperty(), it -> this.loadVersion()));
holder.add(FXUtils.onWeakChangeAndOperate(GameDirectoryManager.selectedInstanceProperty(), it -> FXUtils.runInFX(this::loadVersion)));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里为什么要加 runInFX

@Glavo

Glavo commented Jul 22, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: d4174144d1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Glavo
Glavo merged commit 36bd7d4 into HMCL-dev:main Jul 22, 2026
3 checks passed
@CiiLu
CiiLu deleted the fffffx branch July 22, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]

2 participants