Definitely try to implement some sort of "com-like" reference counting mechanism when passing objects to and from unmanaged code. You never know when the GC might collect your delegates, and you're stuck with bad pointers. Can really be hard to diagnose without a library like SysLibs. I usually have a class used for interop with native code and store a Dictionary<long,object> to keep objects alive. When unmanaged code is done using it, simply remove the object from the dictionary (unmanaged code must know the long corresponding to the object). This approach has worked very well when interoperating with C-C++-Google V8 for me, and I'm sure the same approach could also work for Java interop as well.