J/Direct and Raw Native Interface (RNI) are complementary technologies. Using RNI requires that DLL functions adhere to a strict naming convention, and it requires that the DLL functions work harmoniously with the Java garbage collector. That is, RNI functions must be sure to call GCEnable and GCDisable around code that is time-consuming, code that could yield, code that could block on another thread, and code that blocks while waiting for user input. RNI functions must be specially designed to operate in the Java environment. In return, RNI functions benefit from fast access to Java object internals and the Java class loader.
J/Direct links Java with existing code such as the Win32 API functions, which were not designed to deal with the Java garbage collector and the other subtleties of the Java run-time environment. However, J/Direct automatically calls GCEnable on your behalf so that you can call functions that block or perform UI without having a detrimental effect on the garbage collector. In addition, J/Direct automatically translates common data types such as strings and structures to the forms that C functions normally expect, so you don't need to write lengthy glue code and wrapper DLLs. The tradeoff is that DLL functions cannot access fields and methods of arbitrary Java objects. In this release, they can only access fields and methods of objects that are declared using the @dll.struct directive. Another limitation of J/Direct is that RNI functions cannot be invoked from DLL functions that have been called using J/Direct. The reason for this restriction is that garbage collection can run concurrently with your DLL functions. Therefore, any object handles returned by RNI functions or manipulated by DLL functions are inherently unstable.
Fortunately, you can use either RNI or J/Direct (or both). The compiler and the Microsoft VM allow you to mix and match J/Direct and RNI within the same class as your needs dictate.