【问题标题】:IPC with gui (Java & Native code)带 gui 的 IPC(Java 和本机代码)
【发布时间】:2011-06-19 21:42:36
【问题描述】:

我的申请由两部分组成 -

Java 中的一些 GUI 逻辑。 本机代码(主要是 Delphi)——GUI 实现本身。

Java 使用本机代码进行琐碎的操作,例如打开窗口和响应用户输入事件 - 实现是通过 JNI 完成的。

我有兴趣将双方划分为不同的流程 - 在不挂gui的情况下在它们之间实现IPC的最佳方法是什么? 我倾向于 TCP 套接字或共享内存,但在我深入研究之前,我很想听听一些意见。 性能和简单的实现是我主要关心的问题。

提前致谢。

【问题讨论】:

  • 以我有限的经验,套接字可以很好地解决这个问题。如果您的 GUI 是 Swing GUI,则需要注意在后台线程上完成进程间通信。
  • 我不明白你为什么要这样做。多个流程对我来说听起来更复杂。
  • Delphi 无法在 64 位操作系统上编译。再加上原生代码在极端情况下容易崩溃。
  • @curious 它会在不同的进程中崩溃。 64 位编译器即将推出。 FreePascal 非常好,支持 64 位。在 64 位操作系统上运行 32 位代码有什么问题?
  • 一个 32 位进程被限制为 4GB(甚至更小),我的应用程序很容易因为 OutOfMemory 异常而崩溃。即使 64 位编译器出现,它也会是新鲜的,因此容易出错。当只有本机端崩溃时,其他进程可以识别并优雅地退出或恢复。当我说我有充分的理由这样做时,请相信我。

标签: java delphi ipc multiprocessing native-code


【解决方案1】:

如果您的问题与内存消耗有关

如果您的内存不足(正如您的 cmets 所建议的那样 - 但您应该在主要问题中更好地写下这一点:您提供的详细信息越多,您得到的答案就越好)。

为什么要混合 Java 和 Delphi? Java 可能不适合处理超过 1 GB 的内存,因为它用于常见任务的内存消耗较高,而且它的内部 GC。即使您在 64 位中运行 JVM,您也会面临新的扩展问题:您必须编写非常具体的代码来处理 Java 的巨大内存。

公平地说,问题不是来自 Delphi,而是来自 Java 内存消耗。因此,恕我直言,您应该更好地使用本机代码对数据层进行编码。 Java 可能会增加您的问题。

你可以:

  • 使用Free Pascal Compiler 从 Delphi 代码编译 64 位库,然后从主 32 位 Delphi 应用程序或使用 JNI 使用 Memory Mapped file as bridge 从 Java 调用它。
  • 更改访问数据的方式。您可能不需要一次拥有所有这些千兆字节的数据。您可以将它放在磁盘上,然后通过索引访问它,该索引将保留在 RAM 中。如果您使用 Delphi,您应该使用自己的文件处理(您可以使用我们的 BigTable library 之类的东西进行存储和索引访问),或者使用数据库(甚至是 SQlite3 is able to handle GB of data,因为它的限制约为 140 TB,具有强大的SQL 用于仅检索数据)。
  • 如果您真的需要留在 Java 中,您可能会使用一些 DB 而不是普通的内存结构。您可以从 Java 或纯 Java DB 使用 SQLite。我怀疑它会减少你的内存消耗。

主要方法是:只在内存中保留需要的内容,并使用 Map/Reduce 算法或某种索引。

如果您的问题是在 Java 和 Delphi 之间混合 GUI

根据我的实验,这可能很困难,因为 JNI 倾向于使用自己的线程,而 VCL 期望它的所有进程都在主线程中运行。

所以你可以:

  1. 创建一些 Delphi 方法,在从 JNI 调用时运行 VCL Synchronize 方法以更新屏幕。
  2. 依靠 Windows GDI 消息通信,即在 Delphi 代码中创建您自己的 WM_USER* 处理程序,然后通过发送一些低级 PostMessage 或 SendMessage API 从您的 Java 代码刷新屏幕内容。按照设计,这将是线程安全的。
  3. 使用无状态方法:我非常喜欢。就像在 HTTP 中一样,您的用户界面将充当客户端,并会定期向数据层(充当服务器)请求刷新数据。所有这些过程都将保留在主线程中,并且可以通过 Timer 轻松完成。使用计时器,每次刷新 500 毫秒就足够了,您的主应用程序将保持反应状态。

在所有情况下...

对于 IPC,内存映射文件比套接字快,但 GDI 消息在处理少量数据时是理想的。套接字是很好的候选者,并且在本地机器上也很快:如果传输的数据量只有几 KB(例如高达 1 MB),内存映射文件的小开销将不会很明显;如果您需要创建应用程序的轻客户端版本,它仍然可以工作。

【讨论】:

  • 感谢您的详细回复。我省略了大部分细节,因为它们无关紧要——系统已经启动并呼吸了一段时间。 Java 中有大量代码,因此用本机代码重写它是不可能的。至于实现一个数据库 - 我们已经在使用一个。问题是有时应用程序实际上需要手头的大量数据,并且数据操作速度非常快,因此在中间添加 IO 可能会降低应用程序的速度。
  • 不过,我们正在寻找其他解决方案(实施 IPC 只是我们愿意检查的另一个方向)。尽管如此,这是一个非常有趣的方向,感谢您引起我的注意。至于您在“在 Java 和 Delphi 之间混合 GUI”下建议的其他解决方案,我们在该领域没有任何问题(JNI 通信层工作得很好)。最后,正如我在其他帖子中提到的,我不确定 FPC 是否足够成熟,但我愿意研究一下(我知道它不会编译 Delphi 2010 代码)。
  • @George FPC 是一个成熟的编译器,性能优于 Delphi 编译器,例如用于浮点操作(它能够使用 SSE 操作码),以及跨平台/多操作系统支持。当然,它不会使用 Unicode 字符串进行编译,或者将在 Delphi 2010 中引入增强的 RTTI。泛型和属性可用,但实现方式与 Delphi 的编译器不同。而且,当然,您没有用于构建 UI 的 VCL。所以它不是德尔福的克隆。它是现代对象帕斯卡的另一个端口,非常适合构建计算密集型库。
  • 不幸的是,该项目严重依赖 Unicode 字符串和 VCL,因为它本身就是 GUI 层。另外 - 我们还有一些其他代码可能无法转换为 64 位,所以这个选项现在似乎不太合理。
【解决方案2】:

您回答的问题取决于您的要求(假设您有充分的理由以这种方式划分应用程序):

如果您需要执行“琐碎”的任务,即不需要大量数据传输,那么使用套接字可能会更好。尽管如此,您仍需要创建一个协议,例如尊重字节顺序。另请注意,传输数据会减慢您的 gui 响应速度。

如果您需要传输大量数据,使用共享内存可能性能更高。请注意,在这里您需要自己进行簿记,这是由 tcp 实现完成的(例如传输/接收缓冲区)。使用这个需要协议的问题变得更糟了。

【讨论】:

  • 大部分原生调用只涉及原语,除了一些涉及对象的特殊情况。我应该期望我的 gui 响应变得多慢?如果它以微秒为单位,我猜它不会很明显..?
  • 如果您的 java 应用程序处于空闲状态,不要期望传输几个字节会产生太多开销。 (即应该没问题)
  • “减慢你的 gui 响应”根本不是真的,有分钟。三种方式如何将任何进程移动到后台任务,请删除此词
  • 实际上用户不会注意到低于 100 毫秒的延迟,除非应用程序用于自定义数据输入,否则几乎不会注意到长达一秒的延迟。对于网站,大多数用户已经习惯了几秒钟或更长时间的延迟!忘记性能 - 这不会是一个问题。
【解决方案3】:

如果您想要一个简单的实现,请不要将应用程序分成两个进程。就性能而言,这不是问题,但是您在单个应用程序所需的复杂性之上增加了一个复杂度。您需要有充分的理由将应用程序划分为多个进程,以克服使用此架构交付相同功能所花费的时间和精力。

【讨论】:

    猜你喜欢
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多