JNI error : Local reference table overflow 512 entries - java

My function looks like below. And it is getting executed for a number of times.At certain point it is crashing at jobject nvarObject = env->GetObjectField (var1, nvar1) giving error JNI error : Local reference table overflow 512 entries.
Could anyone look into this issue and throw some light.

All JNI methods that return a jobject or similar object reference are creating local references in the reference table. These references get automatically cleaned up when you return control to the JVM, but if you are creating many references (for instance, in a loop), you'll need to clean up them up manually.
You're on the right track by calling DeleteLocalRef on the cls reference, but notice that GetObjectField also returns a jobject, so the reference returned there should be deleted before exiting the function, as well.
Also make sure to clean up any existing references before returning from error conditions!
Another way to do this: at the top of the function that you're calling in a loop, call PushLocalFrame( env, 5 ) and call PopLocalFrame(env) before any place in the function where you return. This will automatically clean up any references created during that function call. The second argument is the number of local references you want in the frame -- if you need more than 5 local references during the execution of the function, use a value higher than 5.

Related

How to invoke method of an object whose reference id is stored in String? [duplicate]

My question is relate to security level of JVM
How we can we get the object from memory by proving hash code?
Today i was thinking. I create an object of class A in an execution environment One. And get the hash code from here of that object.
Now in another execution environment i want to get back class A object by providing hash code.
I think it is possible. Because when I execute environment one. Again and again i get that JVM return the same hash code.
Means it first find the object in its cache. If it get the reference, it just return it.
So now back to question, we have to understand what data is copied when we
write =.
Object a=new Object();// here as we know reference of new object will be stored in refvar a.
Then what in actual is passes through.
If we get what data is passed by =(equal operator). We will able to get the object from memory.
Thanks
How we can we get the object from memory by proving hash code?
You can't without access to the internals of the JVM. Even then you would need to scan every object in memory. You would also have the problem than multiple objects with the same hashCode. BTW: By default objects don't have a hashCode until you ask for one.
I think it is possible. Because when I execute environment one. Again and again i get that JVM return the same hash code.
This only works because you are recreating the exact conditions where the hashCode as generated, the slightest changes and you would get different hashCodes.
Means it first find the object in its cache. If it get the reference, it just return it.
By it you mean a cache you would need to maintain, no such cache exists in the JVM.
So now back to question, we have to understand what data is copied when we write =.
Object a=new Object();// here as we know reference of new object will be stored in refvar a.
Then what in actual is passes through.
The reference is passed, like you said. Nothing else.
I guess it is irrelevant since hash code may or may not be related to memory address
take a look documentation
in general each JVM has its own memory stack so whether you can access object from other JVM is depending on JVM implementation and I guess it is rarely possible.

Android JNI C++ Code always get "same" jobject value for 2 different SurfaceView object

In Android JAVA code:
public native int addRenderer(int channel, Object glSurface);
Context context = getApplicationContext();
SurfaceView svRemotePartyA = new SurfaceView(context);
SurfaceView svRemotePartyB = new SurfaceView(context);
addRenderer(0, svRemotePartyA);
addRenderer(1, svRemotePartyB);
In Android JNI C++ code:
extern "C" jint JNIEXPORT JNICALL Java_addRenderer(
JNIEnv* jni,
jobject j_vie,
jint channel,
jobject surface) {
LOG(LS_INFO) << "Java_addRenderer(): surface=" << surface;
// some processing
}
When I run the programme, I always read the following log! both SurfaceView object have same value in JNI C++ code log output:
(render_manager.cc:175): Java_addRenderer(): surface==0xbeed6120
(render_manager.cc:175): Java_addRenderer(): surface==0xbeed6120
What's the problem?
You look at local references, which should never be used beyond the context of the same JNI method. If you get a global reference for this jobject, you will get 2 different ones.
You should not attempt to associate a meaning with the specific bit pattern of a JNI reference.
For example, in Dalvik, local references are just indices into a table on the stack. If you make the same call several times with different objects, you will see the same "value" for the reference each time, because the object reference is sitting in the same place in the local reference table.
(It's not quite that simple -- Dalvik actually tucked a trivial serial number into the reference to make it easier to tell when a local ref was used after it had been reclaimed -- but you get the idea.)
Similarly, you cannot make the assumption about global references. If you create two global references to the same object, it's very likely that those references will have different 32-bit values.
Every VM is different. Old (pre-ICS) versions of Dalvik actually passed raw pointers around, and you could compare the reference values to determine if two objects were the same. The switch to indirect references required fixing up a few things.
If you want to tell if two objects are the same, you need to have references to both, and use the JNI IsSameObject() function.
Some additional background is here.

Is this still WeakReference?

I am creating a WeakReference and keeping it somewhere.
WeakReference<MySpecialObject> mWeakReference = new WeakReference<MySpecialObject>(new MySpecialObject("My","Special","Data"));
But some other external library(which I don't what it is doing it) really needs MySpecialObject instance. When I used something similar below:
ExternalLibraryThingy#useItWisely(mWeakReference.get());
end of part #1
after some time I do call
ExternalLibraryThingy#doSomethingUsefull(); //which I dont know it kept a reference while calling "useItWisely" method.
end of part #2
Question
Until the end of part #1, is my in place created MySpecialObject object still weakly referenced? I mean if I call mWeakReference.get(), is there any chance of getting null? In other words can OS garbage collect it at will?
Until the end of part #2, if the ExternalLibraryThingy made and assignment while useItWisely and using that assigned value while doSomethingUsefull, can it throw a NullPointerException?
I guess one simple answer can be the answer for both of the question. Thanks in advance.
You passed the dereferenced object to the ExternalLibraryThingy#useItWisely method. The external library does not care that you retrieved the object from a weak reference.
So whether the object has strong references in the external library depends entirely on the method that you called on it. Without knowing what the method does, it is impossible to know whether the object will still be referenced.
As for your second question, the library had the MySpecialObject reference directly. From the point of view of the external library, it is not going to be randomly replaced with null.

Correct usage of DeleteLocalRef in JNI

Here is the sample jni method where I create a string and return it to the calling java method:
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
char test[100];
sprintf(test, "Test%03d.txt", rand()/100);
jstring returnVal = (*env)->NewStringUTF(env, test);
(*env)->DeleteLocalRef(env,returnVal);
return returnVal;
}
I was expecting the jstring to be invalid in the calling java method since I deleted the local reference. But the reference is still valid. I explicitly called System.gc() to see whether the GC clears it, but it didn't happen.
According to this: http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html
"Bug: Calling DeleteLocalRef() and continuing to use the deleted reference
It shouldn’t need to be said that it’s illegal to continue to use a reference after calling DeleteLocalRef() on it, but because it used to work, so you may have made this mistake and not realized. The usual pattern seems to be where native code has a long-running loop, and developers try to clean up every single local reference as they go to avoid hitting the local reference limit, but they accidentally also delete the reference they want to use as a return value!
The fix is trivial: don’t call DeleteLocalRef() on a reference you’re going to use (where “use” includes “return”)."
I am little confused about the inconsistency.
What SDK level are you targeting? If you target 13 or lower (pre ICS) then you get the old JNI behaviour and this code should work (though it's still technically incorrect)
If you target 14 (ICS) or higher then the code shown will fail with the giveaway error:
memory map fault addr deadd00d
Note, the code will also work if you target SDK 14+, but run the app on an earlier version of Android

In java, how can we destruct an instance of a class from a method within the class

I approached it similar to the case of deleting any usual object, ie, simply making the reference null and letting the Garbage Collector do its job.
However for equating to null within a class, the only reference to the object is "this". So is the code for the following class valid:
class A{
public A(){
//Init
}
public void method destruct(){
if(someCondition){
this=null; //Is this statement valid? Why / Why not?
}
}
}
You don't "destruct" objects in Java. This is wrong-headed. Don't do it.
Objects are created on the heap in Java. They live as long as there's a reference that points to them. The garbage collector cleans up the mess.
You should certainly do what you can to make sure that you don't accumulate and hold onto references unnecessarily (e.g. Listeners in Swing).
But your proposal is not the right thing at all. Cease and desist.
this=null; //Is this statement valid? Why / Why not?
It is not valid Java because this is not an lvalue; i.e. not something you can assign to. This is a compilation error, just like 42 = i; is a compilation error.
(The JLS says the following about assignments: "The result of the first operand of an assignment operator must be a variable, or a compile-time error occurs." - JLS 15.26.1 The JLS text then goes on to list the different things that qualify as variables, and this is not one of them.)
Besides, as duffymo says, it is a totally wrong-headed thing to do in Java. Just let the GC do its job.
NOTE: What you suggest is highly unlikely to be useful.
What you can do is use delegation.
class A {
private AImpl impl = new AImpl();
public void close() {
if (impl != null)
impl.close();
impl = null;
}
}
As all references are indirect, you can ensure there is only one reference to the real object and clear it.
Proxies in some OSGi containers do this when a component is unloaded. As the container has little control over the lifecycle of the references, it would make it difficult to ever unload a library (the implementation).
Your goal is deeply misguided.
Either someone outside the instance holds a non-weak reference to it. Then it will not be collected no matter what you do inside. Or no one does, then it will eventually be collected, no matter what you do inside. In either case, this=null would make no difference, even it were legal java code. Don't do it. If you are concerned about object lifetime and memory exhaustion, look out side the object that you want to get rid of.
Setting this = null is like trying to say that an object doesn't reference itself. It always implicitly references itself. You need to find what other objects might be referencing this one and clear their references instead. Usually, this happens automatically because most objects are retained through local variables that are on the stack. When I say "retained" I mean that they are referenced through a chain of references that ultimately leads to a variable on the stack. When you leave the method, the reference is cleared. But if you have a static variable referencing this object that might be a case where you must explicitly set it null.
For the java garbage collector to pick up your class it should not be referenced be OTHER classes.
The statement this=null; is illegal because the left hand side of an assignment must be a variable.
There is no way to explicitly delete the particular reference in Java. Java does this to avoid hanging references. If you delete an object then other objects refer to it can potentially try to access the data and get a reference to invalid data.
You shouldn't be trying to delete objects anyways, just move all references to the object to null.
No. An instance object could be deleted by the GC when no reference points to it, that its, from all running threads could not navigate till the object. When you are in the object executing a method, this method is invoked from outside, so there is a reference to the object. The object itself can not be destroyed, as a reference to it still remains outside.
Consider another approach for memory management.
In methods this is reference to object on which current method is invoked so it should not be possible to changed it. Think of this as final reference.
Life cycle of objects are ruled by the JVM, due this reason an object cannot decide when itself is no longer needed. What you could do is put some effort on the references to this object. Type of references could be used in order to point the "importance" of the object.
The basic types of references in java can be found here:
More here: http://docs.oracle.com/javase/1.3/docs/api/java/lang/ref/package-summary.html
Discussion about the references here:
What is the difference between a soft reference and a weak reference in Java?
and
Understanding Java's Reference classes: SoftReference, WeakReference, and PhantomReference
You can call :
System.gc() or RuntimeUtil.gc() from the jlibs
but if you do that you mess with the JVM runtime.
If you set refernce to null, the object still exists , its just its' reference won't refer to this object and at the next time GC will be invoked it will destroy the object(unless other references refer to it).
No the above code is not valid. The reference this of a class only lasts as long as the JVM is being executed. Setting this == null will infact give you a compiler error because though this is termed as reference it is actually a value and you can't assign anything to a value.
Also it is unnecessary since this is valid for only as long as the execution is in that code and GC cannot claim an object which is still executing. However as soon as the execution ends for the object, this will also be lost and the object will automatically become available for GC (i.e. if no other reference to the object exists)
This is a compilation error. You cannot assign NULL to 'this'. Keyword 'this' can be used on the right side of equals (with the exception that left hand is not NULL. Reason: nothing can be assigned to null).
For destruction,in java, you have a GC who can do this job for you behind the scenes.
Please note that for user defined objects you can still do something like -
object reference = null;
However 'this' cannot be used on left side of equals.
The very reason why the execution thread is inside the destruct() method tells me that there is a caller that is holding a reference to this instance of class A. So, nevertheless, you cant do anything like "this = null" in java - it would not have helped, even though it was allowed in java. You cant destruct to objects in java.

Categories

Resources