当有多个 AWT-EventQueue 线程时如何选择

2023-12-30

我使用 DLL 注入和一些 jni 技巧成功地将自己的 Java 代码注入到正在运行的 Oracle Forms 应用程序中。 (Windows 7、32 位、Oracle Forms 11、JRE Java 8)

我能够遍历组件树并查询和设置一些基本 Java 对象中的值,例如来自类的对象oracle.forms.ui.VTextField

当我尝试模拟用户点击时,我陷入了困境oracle.apps.fnd.ui.Button

我尝试了两件事:

  1. 打电话给simulatePush的方法AbstractButton class
  2. 打电话给activate的方法PushButton class

(这两个类位于类层次结构中Button)

结果相同: 1. 首先,它工作正常:当按钮是“搜索”按钮时,搜索完成并显示结果。 2.然后,它立即中断该应用程序,并弹出一条消息FRM-92100 Your connection to the Server was interrupted.

从那里,应用程序被挂起。

Update:看来导致与服务器断开连接的错误是:

java.lang.SecurityException:此 KeyboardFocusManager 不是 安装在当前线程的上下文中 java.awt.KeyboardFocusManager.checkCurrentKFMSecurity(来源未知) 在 java.awt.KeyboardFocusManager.getGlobalFocusOwner(来源未知) 在 java.awt.KeyboardFocusManager.processSynchronousLightweightTransfer(未知 来源)于 sun.awt.windows.WComponentPeer.processSynchronousLightweightTransfer(本机 方法)位于 sun.awt.windows.WComponentPeer.requestFocus(未知 源)位于 java.awt.Component.requestFocusHelper(未知源)位于 java.awt.Component.requestFocusHelper(来源未知)位于 java.awt.Component.requestFocus(来源未知)位于 oracle.forms.handler.UICommon.updateFocus(来源未知)位于 oracle.forms.handler.UICommon.setFVP(来源未知) oracle.forms.handler.UICommon.setFVP(来源未知) oracle.forms.handler.UICommon.onUpdate(来源未知)位于 oracle.forms.handler.ComponentItem.onUpdate(来源未知)位于 oracle.forms.handler.JavaContainer.onUpdate(来源未知)位于 oracle.forms.handler.UICommon.onUpdate(来源未知)位于 oracle.forms.engine.Runform.onUpdateHandler(来源未知)位于 oracle.forms.engine.Runform.processMessage(来源未知)位于 oracle.forms.engine.Runform.processSet(来源未知)位于 oracle.forms.engine.Runform.onMessageReal(来源未知)位于 oracle.forms.engine.Runform.onMessage(来源未知)位于 oracle.forms.engine.Runform.processEventEnd(来源未知)位于 oracle.ewt.lwAWT.LWComponent.redispatchEvent(来源未知)位于 oracle.ewt.lwAWT.LWComponent.processEvent(来源未知)位于 oracle.ewt.button.PushButton.activate(来源未知)位于 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) at sun.reflect.NativeMethodAccessorImpl.invoke(来源未知)位于 sun.reflect.DelegatingMethodAccessorImpl.invoke(来源未知)位于 java.lang.reflect.Method.invoke(来源未知)位于 CustomAWT.run(CustomAWT.java:34)位于 java.awt.event.InitationEvent.dispatch(来源未知)位于 java.awt.EventQueue.dispatchEventImpl(来源未知)位于 java.awt.EventQueue.access$400(来源不明)位于 java.awt.EventQueue$2.run(来源未知)位于 java.awt.EventQueue$2.run(来源未知)位于 java.security.AccessController.doPrivileged(本机方法)位于 java.security.AccessControlContext$1.doIntersectionPrivilege(未知 源)位于 java.awt.EventQueue.dispatchEvent(未知源)位于 java.awt.EventDispatchThread.pumpOneEventForFilters(来源未知) 在 java.awt.EventDispatchThread.pumpEventsForFilter(来源未知) 在 java.awt.EventDispatchThread.pumpEventsForHierarchy(未知 来源)位于 java.awt.EventDispatchThread.pumpEvents(来源未知) 在 java.awt.EventDispatchThread.pumpEvents(来源未知) java.awt.EventDispatchThread.run(来源未知)

我的代码在这里:CustomAWT.run(CustomAWT.java:34)并被称为invokeLater。问题可能是:当调用oracle.ewt.button.PushButton.activate方法,我不在正确的美国东部时间。

使用 Java 控制台中的“列出线程”,我得到:

Dump thread list ...
Group main,ac=30,agc=2,pri=10
    main,5,alive
    traceMsgQueueThread,5,alive,daemon
    Timer-0,5,alive
    Java Plug-In Pipe Worker Thread (Client-Side),5,alive,daemon
    AWT-Shutdown,5,alive
    AWT-Windows,6,alive,daemon
    AWT-EventQueue-0,6,alive
    SysExecutionTheadCreator,5,alive,daemon
    CacheMemoryCleanUpThread,5,alive,daemon
    CacheCleanUpThread,5,alive,daemon
    Browser Side Object Cleanup Thread,5,alive
    JVM[id=0]-Heartbeat,5,alive,daemon
    Windows Tray Icon Thread,5,alive
    Thread-13,5,alive
Group Plugin Thread Group,ac=3,agc=0,pri=10
    AWT-EventQueue-1,6,alive
    TimerQueue,5,alive,daemon
    ConsoleWriterThread,6,alive,daemon
Group http://xxxx.xxxx.xxxxx.xx:8001/OA_JAVA/-threadGroup,ac=13,agc=0,pri=4
    Applet 1 LiveConnect Worker Thread,4,alive
    AWT-EventQueue-2,4,alive
    thread applet-oracle/apps/fnd/formsClient/FormsLauncher.class-1,4,alive
    Applet 2 LiveConnect Worker Thread,4,alive
    thread applet-oracle.forms.engine.Main-2,4,alive
    Forms-StreamMessageReader,4,alive
    Forms-StreamMessageWriter,4,alive
    HeartBeat,4,alive
    Busy indicator,1,alive,daemon
    TaskScheduler timer,4,alive
    CursorIdler,4,alive
    Thread-14,4,alive
    Flush Queue,4,alive
Done.

所以,有THREE AWT-EventQueue线程...现在的问题是:如何查询/检索正确的线程,以及如何使Runnable传递给invokeLater在“好线程”中运行(我猜好的线程是最后一个(AWT-EventQueue-2)


经过大量的实验和谷歌搜索关键字,如EventQueue and ThreadGroup我终于找到了解决方案(在为我工作类别,请注意)。

我用sun.awt.AppContext班级。一些文档和来源here http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/sun/awt/AppContext.java(grepcode.com)

  1. 获取跑步的集合AppContext正在使用getAppContexts method.
  2. 对于每个检索到的AppContext,得到他的ThreadGroup使用getThreadGroup method.
  3. 随着ThreadGroup对象,使用getName method.
  4. 当线程组的名称以表单应用程序的 http: 地址开头时,检索Object带有键名的属性sun.awt.AppContext.EVENT_QUEUE_KEY, 使用get的方法AppContext.
  5. 检索到的对象是EventQueue。创建一个java.awt.event.InvocationEvent对象,传递你的Runnable到 CTOR,并使用postEvent的方法EventQueue.
  6. Your run方法将在正确的线程中执行。

Remarks:

  • 这个答案是一个特定的、适合我的解决方案,适用于通过 Internet Explorer 链接启动并在 java.exe 进程中运行的 Oracle Forms 应用程序。在这种情况下,3 个线程组如问题所示:main, Plugin Thread Group, and http://xxxx.xxxx.xxxxx.xx:8001/OA_JAVA/-threadGroup你的旅费可能会改变。
  • 如果您不使用完全反射,而是导入sun.awt.AppContext,编译器可能会发出以下形式的警告warning: sun.awt.AppContext is Sun proprietary API and may be removed in a future release这不太酷,但我暂时会接受这一点。
  • In the run方法,我测试OK了simulatePush的方法oracle.ewt.lwAWT.AbstractButton.
  • 这里模拟的方法是invokeLater. For invokeAndWait,需要更多代码postEvent称呼。请参阅一些来源EventQueue类,作为起点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当有多个 AWT-EventQueue 线程时如何选择 的相关文章

随机推荐