AccessViolationException or SharedMemoryException

Problem: When using shared memory in .NET-to-Java projects, you get an AccessViolationException or SharedMemoryException and the program fails.

What’s really happening is that the Java side is failing for some reason.  The failure simply manifests itself as an AccessViolationException or SharedMemoryException.

If the exception occurs on the first proxy call, this is likely a configuration issue.  Examine your application configuration file to see whether the jvm, jnbcore, and bcel elements contain valid file paths.  Also check to see whether your application or the account running it has permission to access these files.  If the file paths are invalid, or the files are not accessible, you will see the AccessViolationException when you make your first proxy call.

If the exception occurs after several proxy calls, the failure is probably caused by an OutOfMemoryError or a StackOverflowError on the Java side, which is causing the Java side to fail.  You can often verify this by temporarily switching to tcp/binary communications and running the Java side in its own console window.  If the Java side fails, you can see the failure in the Java-side console window.

If this is an OutOfMemoryError, the most likely cause is that the Java-side memory allocation limits are being exceeded.  You can increase the Java-side memory allocation using the -Xmx option.  If you are using shared memory, you can specify this through a jvmOptions element in the configuration.  (Please see the section “Configuring the .NET side” in Users’ Guide for more details, and an example of supplying a -Xmx option.)

One other possible cause for an OutOfMemoryError is that sometimes there is an imbalance between the memory pressure on the .NET side (which triggers garbage collection) and the memory pressure on the Java side.  It’s quite possible that the .NET-side proxy is much smaller than the underlying Java object (or the underlying Java object is at the root of a very large object graph).  The underlying Java objects can’t be collected until the corresponding .NET proxy is collected, and there are situations where there’s no pressure to collect on the .NET side, while the Java side really needs garbage collection.  To resolve this problem, every proxy implements the IDisposable interface.  When you call Dispose() on the proxy, the underlying Java object is released and eligible for garbage collection.  You may need call Dispose() on selected proxies once you’re done with them.  Of course, once you do call Dispose() on a proxy, you can’t use it anymore.  Please see on “Garbage collection and object lifecycle management” in the Users’ Guide for details on IDisposable.  There’s also a disposeAll() that’s the equivalent of calling Dispose() on all proxies, but you need to use it judiciously.  disposeAll() is also described in the section “Garbage collection and object lifecycle management” in the Users’ Guide.