问题
As we known, JNI is a bridge between Java and C++. Recently i'm coding for a Java project and it's main module is based on C++ which need to store a large number of GlobalReference
. And it will increase along with activity being opened. Therefore the maximum number (65535) of GlobalReferences
become a serious problem and i have to solve the problem using peculiar method.
So i'm interested in why there is a limit on GlobalReferences
.
Is it only for detecting the memory leaks as other's saying?
回答1:
To my understanding, it's not about detecting memory leaks really, it's about just managing memory altogether. (As for memory leaks, obviously, you shoudn't hang on to a Java object in your native code longer than you have to, global ref or not) Usage of global references is somewhat of an antipattern (when used for problems that can be solved by other means) in most languages, afaik.
Thing with JNI is that your native code is in slave mode, so to say. The JVM is unable to clean up stuff you hold on to in your C code, especially global refs ('cause their lifecycle is indefinite), so these limits are a measure to prevent developers from abusing JNI and shooting themselves in the foot.
Also, I'm a bit curious on what task you're trying to accomplish that you have to store over 65k global references -- I have a feeling that what you're trying to accomplish allows for a different approach, one that doesn't push JNI over the edge.
E.g. right now I'm wiring a native database library to an Android app, the whole setup has to throw hundreds of thousands of db records back and forth and even this case has a solution that doesn't overflow even the local ref table (512 ref limit) let alone the global ref table.
I know it's probably late, but if you care to share your actual task, we might be able to come up with a proper way of dealing with it.
回答2:
It is easy to answer the question 'why'. The Global References table in Android JVM (be it Dalvik or ART) has a limited number of entries because its architects did not think somebody would need more.
They had different limitations to worry about: memory constraints, performance, stability, maintenance efforts.
But after all, this is more of a rhetorical question, and the answer to it is less relevant than practical advises. Which follow:
The limits on references tables in Android JVM are there to stay. Don't expect these tables to become much larger in the next Android release (but maybe some of them will).
Whatever happens in the future releases of Android, the current versions are here to stay. Millions of people are still using Android devices with Gingerbread, which was released in 2010 (0.6% of 2 Billion). As of today, more than 20% have Dalvik JVM on their devices.
If you hit or come close to the limit on the internal JVM tables, you must reconsider your architecture. You cannot trust the behavior of the system when these tables overflow, even if it does not happen every time.
Remember that memory available to your app is also limited, and the more you use, the more likely your app will suffer performance hit in multitasking environment: the kernel can kill it any time if it needs memory for other apps.
You can avoid table overflow if you aggregate your objects on the Java side. E.g. instead of keeping global references to thousands of objects, you can put them in a Java map, or array, and keep in C++ a global reference to the collection. You can manage the collection in C++ using JNI to access Map.put() and Map.remove.
来源:https://stackoverflow.com/questions/45384947/why-does-jni-global-reference-have-maximum-number-limit