有多个线程时如何选择AWT-EventQueue线程 [英] How to choose an AWT-EventQueue thread, when there are several of them
问题描述
我使用DLL注入和一些jni技巧成功地将自己的Java代码注入了正在运行的Oracle Forms应用程序中. (Windows 7、32位,Oracle Forms 11,JRE Java 8)
I successfully injected my own Java code in a running Oracle Forms application, using DLL Injection and some jni trickery. (Windows 7, 32 bits, Oracle Forms 11, JRE Java 8)
我能够遍历Components的树并查询和设置一些基本Java对象中的值,例如来自类oracle.forms.ui.VTextField
I am able to traverse the tree of Components and to query and set values in some basic Java objects, such as those from class oracle.forms.ui.VTextField
当尝试模拟用户点击oracle.apps.fnd.ui.Button
我尝试了两件事:
- 调用
AbstractButton
类的simulatePush
方法 - 调用
PushButton
类的activate
方法
- call the
simulatePush
method of theAbstractButton
class - call the
activate
method of thePushButton
class
(这两个类在Button
的类层次结构中)
(the 2 classes are in the class hierarchy for Button
)
结果相同:
1.首先,它工作正常:当按钮是搜索"按钮时,将完成搜索并显示结果.
2.然后,它立即中断应用程序,并显示一个弹出窗口FRM-92100 Your connection to the Server was interrupted
.
Results were identical:
1. At first, it works fine: when the button is a "Search" button, the search is done and the results are displayed.
2. Then, it immediately breaks the application, with a pop-up saying FRM-92100 Your connection to the Server was interrupted
.
从那里挂起应用程序.
更新: 似乎导致与服务器断开连接的错误是:
Update: It seems that the error which cause a disconnection from the Server is:
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(本机方法)位于 sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)位于 sun.reflect.DelegatingMethodAccessorImpl.invoke(来源未知) java.lang.reflect.Method.invoke(来源未知) CustomAWT.run(CustomAWT.java:34)位于 java.awt.event.InvocationEvent.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(未知来源)
java.lang.SecurityException: this KeyboardFocusManager is not installed in the current thread's context at java.awt.KeyboardFocusManager.checkCurrentKFMSecurity(Unknown Source) at java.awt.KeyboardFocusManager.getGlobalFocusOwner(Unknown Source) at java.awt.KeyboardFocusManager.processSynchronousLightweightTransfer(Unknown Source) at sun.awt.windows.WComponentPeer.processSynchronousLightweightTransfer(Native Method) at sun.awt.windows.WComponentPeer.requestFocus(Unknown Source) at java.awt.Component.requestFocusHelper(Unknown Source) at java.awt.Component.requestFocusHelper(Unknown Source) at java.awt.Component.requestFocus(Unknown Source) at oracle.forms.handler.UICommon.updateFocus(Unknown Source) at oracle.forms.handler.UICommon.setFVP(Unknown Source) at oracle.forms.handler.UICommon.setFVP(Unknown Source) at oracle.forms.handler.UICommon.onUpdate(Unknown Source) at oracle.forms.handler.ComponentItem.onUpdate(Unknown Source) at oracle.forms.handler.JavaContainer.onUpdate(Unknown Source) at oracle.forms.handler.UICommon.onUpdate(Unknown Source) at oracle.forms.engine.Runform.onUpdateHandler(Unknown Source) at oracle.forms.engine.Runform.processMessage(Unknown Source) at oracle.forms.engine.Runform.processSet(Unknown Source) at oracle.forms.engine.Runform.onMessageReal(Unknown Source) at oracle.forms.engine.Runform.onMessage(Unknown Source) at oracle.forms.engine.Runform.processEventEnd(Unknown Source) at oracle.ewt.lwAWT.LWComponent.redispatchEvent(Unknown Source) at oracle.ewt.lwAWT.LWComponent.processEvent(Unknown Source) at oracle.ewt.button.PushButton.activate(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at CustomAWT.run(CustomAWT.java:34) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$400(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
我的代码在这里:CustomAWT.run(CustomAWT.java:34)
,并用invokeLater
调用.问题可能出在:调用oracle.ewt.button.PushButton.activate
方法时,我不在正确的EDT中.
My code is here: CustomAWT.run(CustomAWT.java:34)
and is called with invokeLater
. Problem is probably: when calling the oracle.ewt.button.PushButton.activate
method, I am NOT in the right EDT.
在Java控制台中使用列表线程",我得到了:
Using "List Threads" in the Java Console, I got:
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.
因此,有三个 AWT-EventQueue
个线程...现在的问题是:如何查询/检索正确的线程,以及如何使Runnable
传递给invokeLater
来运行在好线程"中(我想,好线程是最后一个(AWT-EventQueue-2
)
So, there is THREE AWT-EventQueue
threads... Question is now: How to query/retrieve the right one, and how to make the Runnable
passed to invokeLater
to run in the "Good Thread" (I guess that the good one is the last one (AWT-EventQueue-2
)
推荐答案
经过大量的实验和Google搜索,例如EventQueue
和ThreadGroup
之类的关键字,我终于找到了解决方案(在 Works for Me中类别,请注意).
After a lot of experimentation and google searches with keywords like EventQueue
and ThreadGroup
I have finally found a solution (in the Works For Me category, mind you).
我使用sun.awt.AppContext
类.一些文档和资源这里(grepcode.com)
I use the sun.awt.AppContext
class. Some documentation and sources here (grepcode.com)
- 使用
getAppContexts
方法获取正在运行的AppContext
的集合. - 对于每个检索到的
AppContext
,请使用getThreadGroup
方法获取其ThreadGroup
. - 对于
ThreadGroup
对象,请使用getName
方法. - 当线程组的名称以Forms Application的http:地址开头时,请使用
AppContext
的get
方法检索键名称为sun.awt.AppContext.EVENT_QUEUE_KEY
的Object
属性. - 检索到的对象是
EventQueue
.创建一个java.awt.event.InvocationEvent
对象,将您的Runnable
传递给CTOR,并使用EventQueue
的postEvent
方法. - 您的
run
方法将在正确的线程中执行.
- Get a Collection of the running
AppContext
's using thegetAppContexts
method. - For each retrieved
AppContext
, get hisThreadGroup
using thegetThreadGroup
method. - With the
ThreadGroup
object, Use thegetName
method. - When the name of the Thread Group starts with the http: address of your Forms Application, retrieve the
Object
property with key namesun.awt.AppContext.EVENT_QUEUE_KEY
, using theget
method ofAppContext
. - The retrieved object is an
EventQueue
. Create anjava.awt.event.InvocationEvent
object, passing yourRunnable
to the CTOR, and use thepostEvent
method ofEventQueue
. - Your
run
method will be executed in the right thread.
备注:
- 此答案是特定的,对我有用的,通过Internet Explorer链接启动并在java.exe进程中运行的Oracle Forms Application解决方案.在这种情况下,三个线程组将显示为问题:
main
,Plugin Thread Group
和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
的形式发出警告,这不是很酷,但是我暂时会接受. li>
- 在
run
方法中,我使用oracle.ewt.lwAWT.AbstractButton
的simulatePush
方法测试了OK. - 此处模拟的方法是
invokeLater
.对于invokeAndWait
,在postEvent
调用周围需要更多代码.作为起点,请参见EventQueue
类的一些资料.
- This answer is a specific, works for me, solution for an Oracle Forms Application launched via an Internet Explorer link, and running in a java.exe process. In that situation, the 3 Thread Groups are as shown in the question:
main
,Plugin Thread Group
, andhttp://xxxx.xxxx.xxxxx.xx:8001/OA_JAVA/-threadGroup
Your mileage may vary. - If you don't use full reflection, but instead do import
sun.awt.AppContext
, the compiler may emit warnings in the formwarning: sun.awt.AppContext is Sun proprietary API and may be removed in a future release
That's not very cool, but I will live with that, for the time being. - In the
run
method, I tested OK with thesimulatePush
method oforacle.ewt.lwAWT.AbstractButton
. - The method emulated here is
invokeLater
. ForinvokeAndWait
, more code is needed around thepostEvent
call. See some sources for theEventQueue
class, as a starting point.
这篇关于有多个线程时如何选择AWT-EventQueue线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!