My Android application has a native C++ layer and a Java layer. The Java layer accesses the native layer via JNI calls.
Can the C++ layer safely create C++ objects for its own internal use, and store them in C++ member variables? I'm talking about C++ objects that don't need to be accessed by Java code in any way, i.e. they are managed and deleted completely in the C++ layer. In other words, the same object (via a member variable) is accessed throughout multiple JNI calls, but only the C++ layer needs to access it.
I need confirmation in this matter, because I know that there are special JNI methods for handling objects (relevant terms: local reference, global reference, etc.). If I'm correct, these apply only for objects that are visible by (or created for) Java code as well.
Therefore, I suppose that native-only C++ objects can be created and deleted in the usual ways (such as new and delete), and Java doesn't need to know anything about them. No special interoperability considerations are necessary, as long as the objects and any references to them reside exclusively in the C++ layer. Is this correct? Can I define C++ classes and methods in this layer in the same way as if it was a usual C++ application without any JNI/Java interoperability? To be general, is it allowed to instantiate and store plain C++ objects, i.e. objects that are out of the authority of Dalvik/JVM?
Indeed, the JNI methods for handling objects are for the Java objects.
You can create C/C++ objects in any way you can imagine (malloc/new), but: how will you preserve them across JNI calls? (If you need that, of course.) Two options:
Convert the pointer into an integer and pass that integer to Java. (You will have to care about pointers stored in garbage-collected Java objects, you see, the integers do not imply freeing the native memory.)
Have some C/C++ data structure with all the necessary references.
Thread-safety deserves separate consideration; if you try to store pointers in thread-local variables, you probably will never debug the code (you see, there's a life cycle mismatch).
Good results may be achieved with static global variables accessed from just one thread.
And keep in mind that Android may kill and restart your application's process, thus destroying everything stored in static variables, as well as your native data structures.
Related
I've tried searching around for my answer but can't seem to find one.
I was curious if Java and or other modern languages optimize the replication of objects by doing some sort of virtual mapping for the methods. It would seem to be a waste if every time a new instance of a object is created, it would copy the methods associated with it rather then perhaps mapping these to one place in memory.
I can see some cases, such as polymorphism, where it might not work.
This might be more of a fundamentals question but I am very curious how the compiler handles this.
Thanks!
Strictly speaking, it's none of your business:
The Java Virtual Machine does not mandate any particular internal structure for objects.
(JVM Spec)
So, if you were to write your own JVM, and for some reason you chose to put a copy of method code into every in-memory representation of an object, you would be free to do so.
However, there are various aspects of how the language is defined, that mean that it's not possible for two objects of the same class to have methods that differ -- even if they're non-static inner classes, dynamic classes, etc.
Therefore you're right that it would be wasteful of space to duplicate the method code for each instance, and no serious implementation of Java does so.
I am a beginner in Java and I had completed C++.
In C++,the memory allocation for member functions is done at the time they are declared as a part of a class and not when the objects are created,when the objects are created,then only the memory allocation for the instance variables is done,that is for every object memory allocation for instance variable is done seperately and the member functions are shared commonly by all the objects.
In case of instance variables,I know the same case happens in java,but what happens in case of member functions?
In C++;
For e.g. if we have 2 instance variables a and b,and we had created 3 objects x,y,z and let us say we have a member function getData(),
then all the 3 objects have a seperate copy of the two instance variables a and b,but share a common copy of getData().
For instance variables,same is the case in java,but what for member functions?
In Java, the bytecode for the methods exists only once for a class; no copy of the method's bytecode is made for every object. That would be unnecessary and wasteful; the bytecode does not change while the program runs.
So it works the same as what you say for C++:
... the member functions are shared commonly by all the objects.
In Java, member functions are loaded on-demand by the classloader. Since the entire Java standard library is available alongside any Java program, and the program itself may contain any number of classes, this is necessary in order to keep program start times in the range of sanity.
So any time the program needs a class in any way (e.g. to access a static variable or method, or to create an instance of an object) that isn't already loaded, the Java classloader loads that class, which includes the class's member functions. Then, once that class is loaded, it doesn't need to be loaded again if it's needed in the future, because similarly to what you noted in your question, only one copy of the class bytecode is necessary at any given time.
To avoid accumulating more and more loaded classes as the program runs, Java uses garbage collection to unload classes that it knows it can safely unload, similarly to how it uses garbage collection for program data. Those classes can of course be reloaded later if they are needed again. There are, of course, situations in which unloading a class wouldn't work due to the risk that reloading it would cause static variables/code to be reinitialized/run.
This ability to unload and reload classes can also be put to use in debugging: IntelliJ IDEA has a HotSwap feature that allows you to edit and recompile a class while the program is running, unload that class, then reload the new bytecode so you can quickly test ideas. (Wow, I just realized that totally sounded like an advertisement. I'm not affiliated with JetBrains, in case you're wondering.)
I have gone through What code and how does java.lang.reflect.Array create a new array at runtime?,. I understand that they are implemented in native language ('C'), But my question is why almost all methods java.lang.reflect.Array class methods are native .
My guess and understanding is that
To improve performance ? or to allocate continuous memory for arrays by JVM ?
Is my understanding correct about native methods in Array class or Do i miss anything ?
The reflect.Array.newInstance method uses native code because it must use native code. This has nothing inherently to do with performance but is a result of the fact that the Java language cannot express this operation.
To show that it's a language limitation and not strictly related to performance, here is some valid code which creates a new array without directly invoking any native method.
Object x = new String[0];
However, newInstance takes an arbitrary value of Class<?> and then creates the corresponding array with the represented type. However, this construct is not possible in plain Java and it cannot be expressed by the type-system or corresponding normal "new array" syntax.
// This production is NOT VALID in Java, as T is not a type
// (T is variable that evaluates to an object representing a type)
Class<?> T = String.class;
Object x = new T[0];
// -> error: cannot find symbol T
Because such a production is not allowed, a native method (which has access to the JVM internals) is used to create the new array instance of the corresponding type.
While the above argues for the case of newInstance needing to be native, I believe many of the other reflect.Array methods (which are get/set methods) could be handled in plain Java with the use of specialized casting; in these cases the argument for performance holds sway.
However, most code does not use the Array reflection (this includes "multi-valued data structures" such as ArrayList), but simply uses normal Java array access which is directly translated to the appropriate Java bytecode without going through reflect.Array or the native methods it uses.
Conclusion:
Java already provides fast array access through the JVM's execution of the bytecode. HotSpot, the "official" JVM, is written in C++ which is "native" code - but this execution of array-related bytecode is independent of reflect.Array and the use native methods.
newInstance uses a native method because it must use a native method or otherwise dynamically generate and execute bytecode.
Other reflect.Array methods that could be expressed in Java are native methods for a combination of performance, dispatch simplicity, and "why not" - it's just as easy to add a second or third native method.
Arrays are at the heart of all multi-valued data structures. Arrays require using segments of memory on the host machine, which means accessing memory in a safe, and machine specific manner - that requires calls to the underlying operating system.
Such calls are native because to perform them you must move out of java and into the host environment to complete them. At some point every operation must be handed over to the host machine to actually implement it using the local OS and hardware.
I was looking into this and just wondering does Java provide any construct to find out the size of an object?
Unfortunately not. It's relatively complex. e.g. if I create a String object, I have to consider:
the size of the fields of the objects. For primitives etc. that's simple
the size of objects referred to. Each member object is a reference, and not actually contained exclusively within the object under question. e.g. String contains a reference to a char array, but that char array can be shared across multiple Strings (see the source of substring() to understand how - this is known as the flyweight pattern)
the size of any native implementation details in the JVM
No. It goes against the concept of the language. In a real Object Oriented Programming language (not a hacked-together OOP support like C++), Objects are abstract concepts, not bits on the computer. Until and unless you serialize the object, it's treated like an actual object and not a sequence of bits.
Actually i think you can get the size of an object with the help of the Instrumentation class, but the process is a little more complex(you have to specify in the manifest file the premain class, define a Instrumetation agent etc.) compared to the one in C++ where you have at your use the sizeof() function.
One disadvantage is you get the size of the object but not the size of the referred objects(if it has any).
Another way would be, but this is rudimentary, to have your object under test serialised and wrote in a file and have the size of the file(use the ObjectOutputStream and get its size).For further documentation related to this subject and not only read a little bit about Java agents in general and Java probing.Probing the JVM is a very helpful technique especially if you want to make an analisys on performance(objects sizes, running threads, memory leaks etc.).
1) I have a native java function which passes several params and its implementation is a native C++ constructor to create an object and returns a long which is cast from the pointer to object. This object's constructed members are effectively immutable. The C++ object then can do work based on its constructed state.
2) java code that gets the result of the function call safely publishes the longified version of the pointer somewhere (without mutex) and changes a volatile variable to hopefully publish the memory changes in the native C++ object to other threads
Now another thread reads that volatile variable of 2), and then picks up that published long, and calls another native function that accesses that effectively immutable object in the C++ memory space to do some work.
Question: Is that other thread guaranteed to see the fully constructed native object because of the Java Memory Model guarantees about volatiles and fences? I would bet the answer is yes on some platforms, but I see that different chips work in different ways with using fences, and was wondering about all platforms for which java is available.
A co-author of JCIP answered the question on the JSR mailing list for concurrency.
He says: "JMM [makes no] guarantees extending to anything outside the Java heap - or more specifically it only applies to Java fields", but that "In practice the barriers/fences used today are coarse-grained and will affect all memory equally", so "that in practice this [the volatile publishing attempt described in the question] will work fine (as long as you are using normal process memory)".
Another respondent on the mailing list says: "Some of us have definitely considered it a goal to ensure that Java, C, and C++ synchronization works together as expected, with Java synchronization providing the right visibility guarantees for C or C++ variables, and conversely" but adds that "there is no written guarantee of that [behavior]".
What you pass from java code to native code is copied and passed in the appropriate datatypes for the native code (for example C++ has unsigned int while Java does not, null terminated strings etc).
After that, any threading issues are related to the implementation of the native code.
Essentially it is the same an API. What are the contracts for the API? Does it specify that it can be accessed safely by multiple threads or not?
Java doesn't even know about the existence of the native object you created in your C code, so how can its memory model possibly provide any guarantees about it? All that Java knows about, and can guarantee the behavior of, is the volatile long.