# 运行时错误

> 运行期间的异常与故障 —— MainWindow、FrameBuffer、后台线程、构造函数中的 UI。

Source: https://crossfly.dev/zh/docs/troubleshooting/runtime — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 运行时错误

格式：**症状 → 原因 → 修复**。

## `MainWindow` 无法加载（反射错误 / "class not found"）
**原因：** 根类没有继承 `Window`，**或者**没有公共的无参构造函数。
**修复：**
```java
public class MainWindow extends Window {
   public MainWindow() { }   // 无参构造函数（反射所必需）
   @Override public void onShow() throws Exception { super.onShow(); /* … */ }
}
```
（[项目结构剖析](/docs/get-started/project-structure)）

## "FrameBuffer not disposed! Must call Image.apply after Image.getGraphics!"
**原因：** 你在一个 `Image` 上进行了**离屏（off-screen）**绘制却没有提交（commit）。
**修复：** 使用 `Image.getPaint()` 绘制，并用 `paint.finish()`（或 `image.applyChanges()`）收尾，全部放在 `Main.runOnPaintThreadAndWait(...)` 内部：
```java
Main.runOnPaintThreadAndWait(() -> {
   Paint p = img.getPaint();
   // … 在 p 中绘制 …
   p.finish();               // 确认（等同于 img.applyChanges()）
});
```
> ⚠️ 差异：**错误信息**引用的是 `getGraphics()`/`apply()`（旧名称）；真正的方法是 **`getPaint()`** 和 **`finish()`/`applyChanges()`**。（第 18 章）

## 在后台线程中修改组件导致 UI 卡死/损坏
**原因：** 所有 UI 操作都在 **paint 线程**上进行。
**修复：** 通过 `Component.onUI(r)` / `Main.runOnPaintThread(r)` 回到 paint 线程。
```java
new Thread(() -> { var v = calc(); Component.onUI(() -> label.setText(v)); }).start();
```
（[paint 线程](/docs/concepts/the-paint-thread)）

## 在构造函数中构建的 UI 显示为空 / bounds 错误
**原因：** 在构造函数里，屏幕/bounds 还没准备好。
**修复：** 在 `onShow()` 中构建，并调用 `super.onShow()`。（第 7 章）

## `onAction` 中的异常"消失"了却没有让 app 崩溃
**原因：** handler 会被 `Debug.handle` 捕获并**吞掉**——它们不会向上冒泡。
**修复：** 不要依赖异常传播；进行日志记录（`Debug.log`/`Debug.handle`）并检查 `DebugConsole.txt`。
（[错误与日志](/docs/best-practices/tratamento-de-erros-e-logging)）

## 另请参阅
- [渲染问题](/docs/troubleshooting/render) · [构建与 Gradle](/docs/troubleshooting/build-gradle)
