Overview(总览)

Jacob can register Java classes for MS application events or callbacks. (Jacob可以为MS应用程序事件或回调注册Java类。)

Sequence of Events(事件顺序)

The normal flow for this is: (正常的流程是:)

  1. Application thread creates an instance of the event handler and registers it with Jacob (应用程序线程创建事件处理程序的实例并将其注册到Jacob)
  2. The application continues on doing other work. (该应用程序继续执行其他工作。)
  3. Some time later, the MS application takes some action and initiates the event callback. (一段时间后,MS应用程序将采取一些措施并启动事件回调。)
  4. The Java VM receives the event and spins up a new thread to handle it. (Java VM接收该事件并启动一个新线程来处理该事件。)
  5. The Jacob jni EventProxy in the dll is called by the VM. (DLL中的Jacob Jacob Jni EventProxy由VM调用。)
  6. The Jacob jni EventProxy creates Variant objects to handle the parameters of the passed in event. (Jacob jni EventProxy创建Variant对象来处理传入事件的参数。)
  7. The Jacob jni EventProxy sends the name of the callback and the array of Variant objects to the Java InvocationProxy that was registered to catch events. (Jacob jni EventProxy将回调的名称和Variant对象的数组发送到已注册以捕获事件的Java InvocationProxy。)
  8. The Java InvocationProxy uses reflection to map the event name to a method name with the exact same name. (Java InvocationProxy使用反射将事件名称映射到名称完全相同的方法名称。)
  9. The Java InvocationProxy sends the message to the registered event handler and returns if the event handler is of type void (standard behavior). (Java InvocationProxy将消息发送到已注册的事件处理程序,并在事件处理程序的类型为void(标准行为)时返回。)
  10. The Java InvocationProxy sends the message to the registered event handler and returns the Variant that resulted from the call back to the Jacob jni EventProxy that then returns it to the windows calling program. (Java InvocationProxy将消息发送到已注册的事件处理程序,并将由调用产生的Variant返回给Jacob jni EventProxy,然后将其返回给Windows调用程序。)

SWING Issues(摇摆问题)

Swing developers should note that this message comes in on a thread other than the event thread. All objects receiving events that require user intervention or drawing in the UI should use invokeLater() to post requests for actions onto the event queue. Failure to do so will insure random failures in the GUI. Java Web Start (JWS) and other launchers can have additional issues related to the class loader. The Jacob C++ library uses FindClass() to find the Variant class when building the parameter list. FindClass() uses the system class loader which includes only the classes specified at run time or in the CLASSPATH. Most of the application classes in this situation live in an alternate set of class loaders that were created when the launcher located and ran the application classes. This means that the search for Variant will fail usually with the silent and immediate termination of the Java application. The thread classloader probably can抰 be used to try and find the class because this new thread does not have a classloader associated with it other than the system class loader. The end result is that the Variant class needs to be located via other means and that the thread classloader should be set to be the context class loader of the event handler class. (Swing开发人员应注意,此消息来自事件线程以外的其他线程。所有接收需要用户干预或在UI中绘图的事件的对象都应使用invokeLater()将对动作的请求发布到事件队列中。否则,将确保GUI中出现随机故障。 Java Web Start(JWS)和其他启动器可能还有与类加载器有关的其他问题。 Jacob C ++库在构建参数列表时使用FindClass()查找Variant类。 FindClass()使用系统类加载器,该系统类加载器仅包含在运行时或CLASSPATH中指定的类。在这种情况下,大多数应用程序类都位于一组替代的类加载器中,这些加载器是在启动器定位并运行应用程序类时创建的。这意味着,由于Java应用程序的静默和立即终止,对Variant的搜索通常会失败。线程类加载器可能可以用来尝试查找该类,因为此新线程除系统类加载器外没有与其关联的类加载器。最终结果是需要通过其他方式定位Variant类,并且应该将线程类加载器设置为事件处理程序类的上下文类加载器。)

1.8 and 1.9 behavior(1.8和1.9行为)

The Jacob EventProxy class has been modified (off of the 1.8 tree) so that it takes a two step approach towards fixing these problems. (Jacob EventProxy类已被修改(从1.8树开始),因此它采用两步方法来解决这些问题。)

  1. The EventProxy constructor now accepts an extra object, an instance of the Variant class. This gives the EventProxy a way to get to the Variant class and thus to its classloader. All of the callers of the constructor have been modified to pass a Variant object to the EventProxy without programmer intervention. (现在,EventProxy构造函数接受一个额外的对象,即Variant类的实例。这为EventProxy提供了一种到达Variant类并由此到达其类加载器的方法。构造函数的所有调用方均已修改,无需程序员干预即可将Variant对象传递给EventProxy。)
  2. EventProxy first attempts to locate the Variant class using FindClass() (EventProxy首先尝试使用FindClass()定位Variant类)
  3. Failing that, it looks to see if a variant object had been passed in. If so, it calls class() and goes from there. (如果失败,它将查看是否传入了变体对象。如果是,则调用class()并从那里进行。)
  4. If all that fails, it logs a message and then fails in the spectacular fashion of the previous versions. (如果所有操作失败,它将记录一条消息,然后以以前版本的壮观方式失败。)

1.10 behavior(1.10行为)

The Jacob EventProxy class has been modified so that it takes a different approach towards fixing this problem. (Jacob EventProxy类已被修改,因此它采用了不同的方法来解决此问题。)

  1. All objects that request event notification are now wrapped in a Java InvocationProxy so that a standard interface is always presented to the JNI EventProxy object. (现在,所有请求事件通知的对象都包装在Java InvocationProxy中,以便始终向JNI EventProxy对象提供标准接口。)
  2. The EventProxy constructor accepts any Java class. It wraps the class if it is not an InvocationProxy or uses just the passed in object if it is an InvocationProxy. The JNI layer talks to the InvocationProxy instead of talking directly to the event listener as in previous releases. (EventProxy构造函数接受任何Java类。如果不是InvocationProxy,则包装该类;如果是InvocationProxy,则仅使用传入的对象。 JNI层与InvocationProxy对话,而不是像以前的版本那样直接与事件侦听器对话。)
  3. The Java InvocationProxy has a method on it that will return the Variant class that the EventProxy. The JNI code uses this method to acquire the class so that it can call newInstance(). (Java InvocationProxy上有一个方法,该方法将返回EventProxy的Variant类。 JNI代码使用此方法来获取类,以便它可以调用newInstance()。)

Developers can receive call back events in JWS other Java launching programs without implementing any additional code. They should be aware that their callback methods may need to set the class loader. If they expect to create any objects.: (开发人员可以在JWS其他Java启动程序中接收回调事件,而无需实现任何其他代码。他们应该意识到,他们的回调方法可能需要设置类加载器。如果他们希望创建任何对象:)

      Public xxx someHandler(Variant[] foo){
            Thread.currentThread().setContextClassLoader(
                  this.getClass().getClassLoader());
            // do something
      }

There may still be a dual event queue issue in JWS applications that needs to be looked at. (JWS应用程序中可能仍然存在双重事件队列问题,需要研究。)

1.12 Experimental Behavior(1.12实验行为)

Release 1.12 adds experimental support for event handlers that accept java objects as parameters to closer match the signature of the windows callback. New ActiveXDispatchEvents and ActiveXInvocationProxy operate in tandem in the same way as DispatchEvents and InvocationProxy. DispatchEvents overrides getInvocationProxy() to create a new ActiveXInvocationProxy in place of the normal InvocationProxy. ActiveXInvocationProxy has its own invoke() method that uses reflection to call back using java objects as parameters. (1.12版增加了对事件处理程序的实验性支持,这些事件处理程序接受java对象作为参数,以更匹配Windows回调的签名。新的ActiveXDispatchEvents和ActiveXInvocationProxy以与DispatchEvents和InvocationProxy相同的方式串联运行。 DispatchEvents重写getInvocationProxy()以创建一个新的ActiveXInvocationProxy来代替常规的InvocationProxy。 ActiveXInvocationProxy有自己的invoke()方法,该方法使用反射将java对象作为参数进行回调。)

Issues with this approach (这种方法的问题)