C Best way of modifying values in a function - java

I developed with Java since a few years, now I wanted to learn C and I noticed a few differences.
In Java when I want to return something from a function(e.g. read user input i would write
String s;
s = new Scanner(System.in).nextLine();
In C I would write
char s[20];
scanf("%d", name);
The difference is, in Java the function returns a value that can be assigned directly to a variable, while in C the function takes the variable name as an argument(respectivly the pointer to the variable).
I have noticed this with many C functions. When I write my own functions, should I do it like I'm used to in Java, or should I use the C style of assigning/returning values from functions?

The biggest consideration in doing things in C only with return values is lack of exceptions. Unlike Java, where error conditions can be reported outside of regular call/return process, C has no such capabilities. In other words, Scanner has an option of throwing an exception when there is no next line; scanf does not have such an option.
If you would like to return an error status from your function, you are limited to (1) returning it in a static variable (not safe for concurrency), (2) returning it as the return value, or (3) returning it in a separate "error" object. Sometimes options (2) and (3) are combined.
As the result, you will often see C APIs that can fail structured like scanf, when the status is returned as the return value, and the rest of the values are modified through pointers.
if (scanf("%d%d", &i, &j) == 2) {
... // Got 2 numbers
} else {
fprintf(stderr, "Wrong input! Expected two numbers.");
}
APIs that do not fail (say, isalpha(ch) or tolower(ch)) return their value directly.

#DasBlinkenLight has an excellent point: Sometimes you need the return value of a function to pass back an integer indicating an error occurred and what kind of error occurred.
Another reason, as #chmike points out, is that if you wanted to return a string in this case, you would have to use malloc() (C's equivalent of Java's new). But C doesn't have garbage collection, so it must be explictly freed. Because of this, it is often "bad etiquette" to pass to other exterior functions a pointer that must be freed. Who is to say that the programmer even wants memory to be allocated on the heap? Using the heap is expensive, and often the whole reason the programmer is using C is because the program in question needs to be fast.
If the programmer who calls your function wanted to use the heap, they would do so in the case of scanf by calling malloc() themselves, then giving scanf a pointer to the new memory location which you could then fill with your function. That way the caller of scanf can keep track of all the memory that was allocated, and what memory was not.
When APIs do return allocated pointers, it's usually because it can't be avoided, and they explicitly document this and usually provide a function to free the memory properly, as is the case with POSIX regex's regfree or glob's globfree. This way, if the library does allocate the memory, the library also frees it.

Whereas in Java there is such a thing called a garbage collector, in C you are responsible of the memory management.
Java is 'give it to me'.
String s = MyFunction(); // Give it to me.
In Java when you call a function that retrieve data from somewhere it just allocate it transparently and return it, the garbage collector will free it later.
C is 'put it there'.
In C you have to manage the memory. The common practice is to first make some place to put the data then try to retrieve it.
Also your code should be more something like this:
char s[80]; // Static memory allocation, we hope it is enough.
scanf("%79s", s); // Now we retrieve data. (Put it there).
Or something like this:
char* s = malloc(80 * sizeof(char)); // Dynamic memory allocation, we hope it is enough.
scanf("%79s", s); // Now we retrieve data. (Put it there).
// Do stuff with data
free(s); // Be responsible.
So, yes, you should use the C style of assigning/returning values (it make sense, after all you are doing C).
One more point, if you code it like Java here what you will have:
char* MyTest() {
char* a = "pipo";
return a; // Big fail, 'a' is local and will not exist anymore after return.
}
char* MyOtherTest() {
char a[]= "pipo";
char* b = malloc(80 * sizeof(char));
strncpy(b, a, sizeof(a));
return b; // My bet this one will never be freed.
}
That last example breaks a well know good practice rule, the caller should be responsible of allocating/freeing the memory.
The only exception I see is for value type, like simple type or struct.
// Nice and simple.
int MyAdd(int a, int b) { return a+b; }
// Why ? just Why ?
void MyAdd(int a, int b, int* r) { *r = a+b; }

Java is object oriented and returns an object which is a pointer to the object.
In C you can return a pointer as well, but not an array. The C code you show is not correct because s, declared as a pointer to a char, is not initialized. Scanf expect a pointer to a preallocated buffer as second argument. It will write the input string into the buffer. I guess you meant scanf("%d", s);.
The C code you wrote will not work because s doesn't point to an allocated buffer to store the chars. You could define s as char s[1024]; in which case s is equivalent to a pointer to a buffer of 1024 chars.
You could also define s a char *s = malloc(1024*sizeof(char)); which will dynamically allocate the buffer for s. You then need to call explicitly free(s) to release the buffer when you don't need it anymore. This is because C doesn't have a garbage collector as in Java.

well, you should know the main difference between C and Java,
Java is Object Oriented programming while C is not.
in Java almost everything is Object ( except primitives).
The way you called Scanner class is a very bad approach,
you should do it as :
Scanner scanner= new Scanner(System.in);
then call it to get string:
String s = scanner.nextLine();
The reason being is because everytime you call new Scanner(System.in) you assign your scanner to the same Object so it will start over from the start of the System.in meaning, you keep getting the same input over and over.
however in C, its not like this. since there its not an object you call.
So in short just remember in java everything is a reference (except primitive values of cource) to something else while in C its not the case
EDIT:
in terms of sending parameter to a method java can be tricky, because it depends on if you are sending a primitive data or an object.
for this reason it is normally better to get the method return something rather than sending the data that needed to be set as parameter
for example take a look at the scenario:
1. Example 1
public void addOne(int i){
i++;
}
public static void main(String... args){
int i=0;
addOne(i);
System.out.println(i);
}
output= 0;
2. Example 2
public int addOne(int i){
return i++;
}
//output = 1
public static void main(String... args){
int i=0;
i = addOne(i);
System.out.println(i);
}

To read a char array in C, you first have to inialize the actual array with a limit of how long it can be. Somthing like this:
char str[20];
scanf("%s", &str);
Note the %s format string telling scanf to capture a string, %d is for integers.

Related

How to return value from the function without exiting from the function?

I am adding byte arrays from an array list of another array list of bytes. So, basically, I am playing with nested byte arrays. I am able to add the first index of each byte array but I am unable to return it immediately. The function will return the whole byte array when all indexes are added. But, I want to return the sum of each index separately.
public static byte[] final_stream(ArrayList<ArrayList<byte[]>> outerstream) {
ArrayList<byte[]> streams = new ArrayList<byte[]>();
int x = 0;
while (x < outerstream.size()) {
streams = new ArrayList<byte[]>();
for (ArrayList<byte[]> bytes : outerstream) {
streams.add(bytes.remove(0));
}
x++;
return stream_Addr(streams); // Here I want to return the value
}
} // Here it gives error to return byte[]
Your code is wrong on many levels, a quick (probably incomplete) list:
you violate java naming conventions. Method names go camelCase(), and variable names (unless constants), too. And you only use the "_" for SOME_CONSTANT
the term "stream" has a very special meaning in Java. A list is not a stream (but you can create a true java stream from a list by yourList.stream())
and yes, what you intend to do in that while loop is beyond my creativity to interpret. Honestly: throw that away, and start from scratch.
Regarding your real question: every "exit" path of a non-void method needs to either throw an exception or to return something.
Finally: what you intend to do isn't possible like that in Java. A caller calls a method, and that method returns one value and then ends.
What you can do, is something like:
thread A creates someList and passes that to some thread B somehow
thread B manipulates that list object, and by using appropriate synchronization the other thread can access that data (while B continues to make updates)
And the real answer is: you can't learn a new language by assuming that the language supports a concept you know from other languages (like pythons generators) to then invent your own syntax or construct in the new language to then be surprised "gosh, it doesn't work". It goes the other way round: you research if your target language has such a concept, if not, you research what else is offered. Then you read a tutorial about that, and follow that.

reducing Java Garbage Collection for methods returning arrays?

Object A has method B(), and lives for most of the life of the application. B calls object C method D(). D() returns an array holding up to x MyData objects. MyData might be a POD (plain old data)/PDS (passive data structure) or might be more, but a MyData can be reused by calling methods or setting fields; its identity or functionality isn't cast in stone during construction or otherwise.
Currently B() is defined like:
class A {
public B() {
MyData[] amydata = c.D( 5 );
:
:
}
}
Currently D() is defined like:
MyData[] D( int iRows ) {
MyData[] amydata = new MyData[ iRows ];
for ( int i = 0; i < iRows; i++ ) {
if ( no more data )
return amydata;
amydata [ i ] = new MyData();
// calculate or fill in MyData structure.
}
return amydata;
}
A is going to be always, or for a long time (e.g., until the user reconfigures it) be asking for the same number of rows, even though the data will differ.
So what if I have the caller pass in the array reference:
class A {
int iRequestSize = 5;
int iResultSize;
MyData[] amydata = new MyData[ iRequestSize ];
public B() {
iResultSize = c.D( iRequestSize, amydata );
:
:
// use up to iResultSize even though array is potentially bigger.
}
}
// returns number of rows actually used
int D( int iRowsMax, MyData[] amydata ) {
for ( int i = 0; i < iRowsMax; i++ ) {
if ( no more data )
return i;
if ( amydata [ i ] == null )
amydata [ i ] = new MyData();
// calculate or fill in MyData structure.
}
return iRowsMax;
}
I'm a C++ guy and new to Java, but it seems that assuming MyData can be recycled like this, the second version should avoid creating and copying MyData's, as well as eliminating garbage collection?
I would say the second variant is worse.
In the first variant amydata and all the objects referenced by it can be garbage collected as soon as the method B() exits (assuming that B doesn't store a reference to amydata somewhere else.)
In the second variant amydata cannot be garbage collected as long as the instance of A lives.
Consider the case where upon the first call to D() it returns 5 references to MyData objects, but on subsequent calls it returns no more rows. In the first variant the amydata array and the 5 referenced MyData objects can be garbage collected as soon as B() returns. But in the second variant neither the amydata array nor the 5 MyData objects referenced through it can be garbage collected - possibly never during the whole runtime of your application.
Remember: the Java Garbage Collector is optimized for many short-lived objects
Disclaimer: Reading the OP's comments, I have to admit that I didn't get his real intent, i.e. to develop a soft-real-time application, avoiding garbage collection as much as possible, a very special and rare situation in the Java world.
So the following answer does not match his problem. But as a casual reader migrating from C++ to Java might stumble over this question and answer, he/she might get some useful hints on typical Java programming style.
Although the syntax of Java and C++ have quite some similarities, because of the very different runtime environments, you should adopt a different coding style.
As a decades-long Java guy, I'd surely prefer the original method signature. As a caller of the D() method, why should I create the results data structure instead of getting it from the method I am calling? That reverses the natural flow of data.
I know, in good old C times when dynamic memory management meant lots of headache, it was very common to prepare the result array outside of the function and have the function only fill in the results, the way you wrote the second version. But forget about that with Java, and just let the garbage collector do its job (and it's very good at that job). Typically trying to "help" the GC results in code that's in fact less efficient and harder to read. And if you really want to stick to that style, there's no need to pass both the max rows number and the array, as the array itself knows its length (that's different from old-style C arrays), giving the max row number.
You assume
the second version should avoid creating and copying MyData's
That sounds like a misconception about Java's inner workings. Every time you execute a new MyData(...) expression, you create a new instance somewhere on the heap. Providing a MyData[] array doesn't avoid that. Translated to C terminology, the array just holds pointers to MyData objects, not the real objects. And Java instances are hardly ever copied (unless you explicitly call something like object.clone()). It's just the reference (= pointer) to the instance that gets copied when you assign something to a variable.
But even the first version is far from perfect, if I understand its purpose correctly. The D() method itself can determine when there's no more data available, so why should it return an array longer than necessary? With Java arrays that's a bit inconvenient, so typical Java code returns a List<MyData> in similar situations.
One more comment on the MyData() constructor and later "calculate or fill in MyData structure". I know that style exists (and is quite popular in the C family of languages), but it's not predominant in Java, and I especially dislike it. To me, it sounds like asking "Give me a car" and getting just a skeleton instead of a usable car. If I want it to have wheels, an engine and seats, I later have to supply them myself. If a usable car needs the selection of options, I want to supply them when ordering the car / calling the constructor, so that I can honestly call the result a car instead of a skeleton.
And finally a comment on the Java naming conventions: the vast majority of Java code follows the conventions, so your method names beginning with upper case look very strange to me.

Create an inline object and pass as parameter

Hi I come from Java where the following is valid:
System.out.println(new String("Hello World"));
is there a C++ equivalent to passing creating an object or pointer in the constructor and pass it as a parameter at the same time such as.
heap.insert(new Food);
Yes. For example
std::vector<Food> c;
c.emplace_back(constructor arguments for Food);
In general, it is most often the case that objects are not given to method as pointers.
If heap.insert takes a const reference :
void insert(const Food& val);
then you can use it with temporary or existing Food arguments, such as
heap.insert(Food{});
var auto foo = Food{constructor arguments};
heap.insert(foo);
heap.insert(Food(constructor arguments));
or in some cases even
heap.insert({constructor arguments});
heap.insert(new Food);
in of itself is valid C++ syntax. It constructs a new instance of the Food class, and passes it to heap's insert() method.
However, the key fundamental difference you will need to learn when transitioning from Java to C++ is that your C++ application is completely responsible for managing all object's lifetimes. In Java you don't need to think about it. Once an object is no longer referenced anywhere, at some point it'll get destroyed by Java's garbage collector.
C++ makes you responsible for managing each object's lifetime. Whenever your application does not need the object that you constructed here with the new operator, it should be deleted, otherwise you're going to leak memory.
To summarize:
heap.insert(new Food);
is just half the story. The new operator will construct your new class instance, and your heap object's insert() method, presumably, stores the pointer to the new class instance, in some fashion. Somewhere, you will then need to delete that class instance, sooner or later.
Yes. You have to define a class, a constructor for it that accepts parameters, then a function that accepts instances of that class and that's all.
Eventually, add to the class definition a proper copy constructor or pass it by reference.
It follows an example:
struct S {
S(int x) { this->x = x; }
int x;
};
void fn(S s) { }
void cfn(const S &s) { }
int main() {
fn(S{42});
cfn(S{42});
}
Be aware that using new in such a case is one of the easiest ways to incur in a memory leak, so pay attention!!
The examples you gave are too easy.
cout << string("hello World");
// not necessary to contruct a string, but to show that it can be done on the spot
heap.insert(Food()); // construct a Food on the spot...
But in general, if you are talking about anonymous classes and similar things in Java, C++ has this stuff, and it has also the lambda concept which is very powerful ;)
If the function parameter is by value or by const reference, and the type you are passing can be used to construct the object, you can pass it directly. For example:
void print(const std::string& str);
int main()
{
print("Hello world");
}
std::string has a constructor which can accept the string literal, and therefore the code compiles, creating a temporary string object, equivalent to:
print(std::string("Hello world"));
If the constructor takes multiple parameters, you can create a temporary object directly in the function call. For example:
void myfunc(const MyClass& c);
myfunc(MyClass(param1, param2));
In Java new objects are creating using new. In C++, new is not required to create a new object, and should be avoided as much as possible, because it makes it harder to avoid memory leaks. This is one of the most common mistakes programmers coming from Java make.
std::string text;
MyClass c;
c.do_something();
This code is totally valid. text and c are valid objects.
std::string *text = new std::string();
MyClass *c = new MyClass();
c->do_something();
delete text;
delete c;
This code is also valid*. But it takes more typing, and if you forget to delete them, you will get a memory leak.
*Edit: Actually it is not exception safe! All the more reason to avoid new!

java string optimizations - load-in-place algorithm

I need to optimize the actual loading/parsing of a csv file (strings). The best way I know is the load-in-place algorithms and I successfully used it using JNI and a C++ dll that loads the data directly from a file made out of the parsed csv data.
It would have been fine if it stopped there but using that scheme only made it 15% faster (no more parsing of the data). One of the reason it is not as fast as I first thought it would be is because the java client uses jstring so I need to convert the actual data again from char* to jstring.
The best would be to ignore that conversion step and load-in-place the data directly into the jstring objects (no more conversion). So instead of duplicating the data based on the loaded-in-place data, the jstring would be pointing directly into the chunk of memory (note that the data would be made of jchars instead of chars). The real bad thing is that we would need to make sure the garbage collector doesn't collect that data (by keeping a reference to it maybe?) but it should be feasible.. no?
I think I have two options to do that:
1- Load the data in java (no more jni) and use chars that are pointing to the loaded data to create the strings.. but I need to find a way to prevent the duplicating of the data when creating a String.
2- Continue using jni to "manually" create and set the jstring variable and make sure that the garbage collector options are set properly to prevent it from doing anything to it. For instance:
jstring str;
str.data = loadedinplacedata; // assign data pointer
return str;
Not sure if that's possible but I wouldn't mind just save the jstring directly into the file and reload it like that:
jstring * str = (jstring *)&loadedinplacedata[someoffset];
return * str;
I'm aware that this is not the usual Java thing, but I'm pretty sure Java is extensible enough to be able to do that. And it's not like I really have a choice in the matter... the project is already 3 years old and it needs to work. =S
This is the JNI code (C++):
const jchar * data = GetData(id, row, col); // get pointer of the string ends w/ \0
unsigned int len = wcslen( (wchar_t*)data );
// The best would be to prevent this function to duplicate the data.
jstring str = env->NewString( data, len );
return str;
Note: The code above made it 20% faster (instead of 15) by using unicode data instead of UTF8 (NewString instead of NewStringUTF). This shows that if I can remove that step or optimize it, I'd get quite the good performance increase.
I've never worked with JNI, but... does it make any sense to have it return a custom class implementing CharSequence, and maybe a few other interfaces like Comparable< CharSequence >, instead of a String? It seems like you'd be less likely to have data corruption problems that way.
I think first you have to understand why the C++ version runs 15% faster, and why that performance improvement is not directly translatable into Java. Why can't you write the code 15% faster in Java?
Lets look at your problem. You've eliminated the parsing by using a C++ dll. (Why could this not have been done in Java?). And then as I understand it:
You're proposing to manipulate the contents of the jstrings directly
You want to prevent the garbage collector from touching these modified jstrings (by keeping a reference to them), and therefore potentially modifying the behaviour of the JVM and screwing with the garbage collector when it does eventually garbage collect.
Will you 'fix' these references before you allow them to be garbage collected?
If you propose doing your own memory management, why are you using java at all? Why not just do it in pure C++?
Assuming that you wish to continue in Java, when you create a String, it the String itself is a new Object, but the data that it's pointing to is not necessarily. You can test this by calling String.intern(). Using the following code:
public static void main(String[] args) {
String s3 = "foofoo";
String s1 = call("foo");
String s2 = call("foo");
System.out.println("s1 == s2=" + (s1 == s2));
System.out.println("s1.intern() == s2.intern()=" + (s1.intern() == s2.intern()));
System.out.println("s1.intern() == s3.intern()=" + (s1.intern() == s3.intern()));
System.out.println("s1.substring(3) == s2.substring(3)=" + (s1.substring(3) == s2.substring(3)));
System.out.println("s1.substring(3).intern() == s2.substring(3).intern()=" + (s1.substring(3).intern() == s2.substring(3).intern()));
}
public static String call(String s) {
return s + "foo";
}
This produces:
s1 == s2=false
s1.intern() == s2.intern()=true
s1.intern() == s3.intern()=true
s1.substring(3) == s2.substring(3)=false
s1.substring(3).intern() == s2.substring(3).intern()=true
So you can see that although the String objects are different, the data, the actual bytes aren't. So your modifications may not actually be that relevant, the JVM may already be doing it for you. And it's worth saying that if you start modifying the internals of jstrings, this may well screw this up.
My suggestion would be to find out what you can do in terms of algorithms. Development with pure java is always quicker that Java & JNI combined. You've got a much better chance of finding a better solution with pure Java.
Well... seems like what I wanted to do is not "supported" by Java unless I hack it.. I believe it would be possible to do so by using GetStringCritical to get the actual char array address and then find out the number of characters and such but this is way beyond "safe" programming.
The best work around I found was to create a hash table in java and use an unique identifier processed while creating my data file (acting similar to .intern()). if the string was not in the hash table, it would query it through the dll and save it in the hash table.
data file:
numrow,numcols,
for each cell, add a integer value (in my case the offset in memory pointing to the string)
for each cell, add string ending with \0
By using the offset value, I can somewhat minimize the number of strings creation and string queries. I tried using globalref to keep the string inside the dll but that made it 4 times slower.

Passing pointers between C and Java through JNI

At the moment, i'm trying to create a Java-application which uses CUDA-functionality. The connection between CUDA and Java works fine, but i've got another problem and wanted to ask, if my thoughts about it are correct.
When i call a native function from Java, i pass some data to it, the functions calculates something and returns a result. Is it possible, to let the first function return a reference (pointer) to this result which i can pass to JNI and call another function that does further calculations with the result?
My idea was to reduce the overhead that comes from copying data to and from the GPU by leaving the data in the GPU memory and just passing a reference to it so other functions can use it.
After trying some time, i thought for myself, this shouldn't be possible, because pointers get deleted after the application ends (in this case, when the C-function terminates). Is this correct? Or am i just to bad in C to see the solution?
Edit:
Well, to expand the question a little bit (or make it more clearly): Is memory allocated by JNI native functions deallocated when the function ends? Or may i still access it until either the JNI application ends or when i free it manually?
Thanks for your input :)
I used the following approach:
in your JNI code, create a struct that would hold references to objects you need. When you first create this struct, return its pointer to java as a long. Then, from java you just call any method with this long as a parameter, and in C cast it to a pointer to your struct.
The structure will be in the heap, so it will not be cleared between different JNI calls.
EDIT: I don't think you can use long ptr = (long)&address; since address is a static variable. Use it the way Gunslinger47 suggested, i.e. create new instance of class or a struct (using new or malloc) and pass its pointer.
In C++ you can use any mechanism you want to allocate/free memory: the stack, malloc/free, new/delete or any other custom implementation. The only requirement is that if you allocated a block of memory with one mechanism, you have to free it with the same mechanism, so you can't call free on a stack variable and you can't call delete on malloced memory.
JNI has its own mechanisms for allocating/freeing JVM memory:
NewObject/DeleteLocalRef
NewGlobalRef/DeleteGlobalRef
NewWeakGlobalRef/DeleteWeakGlobalRef
These follow the same rule, the only catch is that local refs can be deleted "en masse" either explicitly, with PopLocalFrame, or implicitly, when the native method exits.
JNI doesn't know how you allocated your memory, so it can't free it when your function exits. Stack variables will obviously be destroyed because you're still writing C++, but your GPU memory will remain valid.
The only problem then is how to access the memory on subsequent invocations, and then you can use Gunslinger47's suggestion:
JNIEXPORT jlong JNICALL Java_MyJavaClass_Function1() {
MyClass* pObject = new MyClass(...);
return (long)pObject;
}
JNIEXPORT void JNICALL Java_MyJavaClass_Function2(jlong lp) {
MyClass* pObject = (MyClass*)lp;
...
}
While the accepted answer from #denis-tulskiy does make sense, I've personnally followed suggestions from here.
So instead of using a pseudo-pointer type such as jlong (or jint if you want to save some space on 32bits arch), use instead a ByteBuffer. For example:
MyNativeStruct* data; // Initialized elsewhere.
jobject bb = (*env)->NewDirectByteBuffer(env, (void*) data, sizeof(MyNativeStruct));
which you can later re-use with:
jobject bb; // Initialized elsewhere.
MyNativeStruct* data = (MyNativeStruct*) (*env)->GetDirectBufferAddress(env, bb);
For very simple cases, this solution is very easy to use. Suppose you have:
struct {
int exampleInt;
short exampleShort;
} MyNativeStruct;
On the Java side, you simply need to do:
public int getExampleInt() {
return bb.getInt(0);
}
public short getExampleShort() {
return bb.getShort(4);
}
Which saves you from writing lots of boilerplate code ! One should however pay attention to byte ordering as explained here.
Java wouldn't know what to do with a pointer, but it should be able to store a pointer from a native function's return value then hand it off to another native function for it to deal with. C pointers are nothing more than numeric values at the core.
Another contibutor would have to tell you whether or not the pointed to graphics memory would be cleared between JNI invocations and if there would be any work-arounds.
I know this question was already officially answered, but I'd like to add my solution:
Instead of trying to pass a pointer, put the pointer in a Java array (at index 0) and pass that to JNI. JNI code can get and set the array element using GetIntArrayRegion/SetIntArrayRegion.
In my code, I need the native layer to manage a file descriptor (an open socket). The Java class holds a int[1] array and passes it to the native function. The native function can do whatever with it (get/set) and put back the result in the array.
If you are allocating memory dynamically (on the heap) inside of the native function, it is not deleted. In other words, you are able to retain state between different calls into native functions, using pointers, static vars, etc.
Think of it a different way: what could you do safely keep in an function call, called from another C++ program? The same things apply here. When a function is exited, anything on the stack for that function call is destroyed; but anything on the heap is retained unless you explicitly delete it.
Short answer: as long as you don't deallocate the result you're returning to the calling function, it will remain valid for re-entrance later. Just make sure to clean it up when you're done.
Its best to do this exactly how Unsafe.allocateMemory does.
Create your object then type it to (uintptr_t) which is a 32/64 bit unsigned integer.
return (uintptr_t) malloc(50);
void * f = (uintptr_t) jlong;
This is the only correct way to do it.
Here is the sanity checking Unsafe.allocateMemory does.
inline jlong addr_to_java(void* p) {
assert(p == (void*)(uintptr_t)p, "must not be odd high bits");
return (uintptr_t)p;
}
UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size))
UnsafeWrapper("Unsafe_AllocateMemory");
size_t sz = (size_t)size;
if (sz != (julong)size || size < 0) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
if (sz == 0) {
return 0;
}
sz = round_to(sz, HeapWordSize);
void* x = os::malloc(sz, mtInternal);
if (x == NULL) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
//Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize);
return addr_to_java(x);
UNSAFE_END

Categories

Resources