You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We've observed an issue wherein a reference to an internal member variable appears to become dangling after the class that contains that member is garbage-collected.
Question
Can references returned by @ByRef-annotated functions become dangling? Is there a way to prevent the reference from becoming dangling, or to instruct javacpp to make a copy of the underlying object?
GetNumbersobj = makeGetNumbers( 1000 );
VecVecRvalues = obj.nums(); /// If obj is garbage-collected, does this reference become dangling?
Here, VecVecR and GetNumbers are wrapped types. obj.nums() would return a const reference in C++. The java declaration of nums() is annotated with @ByRef. Full definitions are provided below. On the C++ side of things, GetNumbers is held by a unique_ptr to GetNumbersI.
Definitions
Here, GetNumbers is a wrapper for a C++ class, where the nums() function returns a const reference. This reference points to an internal member variable.
Is it possible for an instance of GetNumbers to be garbage-collected while another variable holds onto the object returned by nums()?
We have a class with a method that returns a vector by const reference:
#pragma once
#include<memory>
#include<vector>namespaceexample {
using R = double;
using VecR = std::vector<R>;
using VecVecR = std::vector<VecR>;
structGetNumbersI
{
virtual VecVecR const& nums() const = 0;
};
using GetNumbersU = std::unique_ptr<GetNumbersI const>;
GetNumbersU makeGetNumbers( size_t size );
} // namespace example
// Targeted by JavaCPP version 1.5.8: DO NOT EDIT THIS FILEpackagecom.voladynamics.example;
importjava.nio.*;
importorg.bytedeco.javacpp.*;
importorg.bytedeco.javacpp.annotation.*;
importstaticcom.voladynamics.example.global.example.*;
@Name("example::GetNumbersI") @Properties(inherit = com.voladynamics.presets.example.class)
publicclassGetNumbersextendsPointer {
static { Loader.load(); }
/** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */publicGetNumbers(Pointerp) { super(p); }
publicnative@Const@ByRefVecVecRnums();
}
Sample code causing crash
Here is roughly the code that causes the issue:
GetNumbersobj = makeGetNumbers( 1000 );
VecVecRvalues = obj.nums();
/// Some expensive computation, that does not directly reference `obj`/// It appears that `obj` gets garbage-collected during this time period/// This code will cause the JVM to crash for newer JVM versions (eg, OpenJDK 17 or 19)doublesum = 0.0;
for (intit = 0; it < 100; it++) {
for (inti = 0; i < values.size(); i++) {
for (intj = 0; j < values.get(i).size(); j++) {
sum += values.get(i).get(j);
}
}
}
When a line of code that references obj is appended to the above, the crash goes away:
GetNumbersobj = makeGetNumbers( 1000 );
VecVecRvalues = obj.nums();
/// Some expensive computation, that does not directly reference `obj`/// It appears that `obj` gets garbage-collected during this time period, if it's not referenced anywhere else in the function/// This code will cause the JVM to crash for newer JVM versions (eg, OpenJDK 17 or 19)doublesum = 0.0;
for (intit = 0; it < 100; it++) {
for (inti = 0; i < values.size(); i++) {
for (intj = 0; j < values.get(i).size(); j++) {
sum += values.get(i).get(j);
}
}
}
/// If this line is uncommented, obj won't be garbage-collected/// System.out.println( obj.nums().get(0).get(0) );
The text was updated successfully, but these errors were encountered:
If using PointerScope isn't an option, we need to make sure that GetNumbers doesn't get deallocated, yes. Unless something after that references it in Java, it might get deallocated since the JVM cannot know that something else in C++ is still referencing it. To prevent that from deallocating C++ objects though, another way to work around that is to set to the "org.bytedeco.javacpp.nopointergc" system property to "true", if that's OK for your application.
Thank you so much for your response! If we enabled nopointergc, would that prevent destructors from being called? This could be problematic for some objects using RAII, and it seems like it would result in most memory being leaked (although please correct me if I'm wrong here)
There is no guarantee that GC ever calls any destructors at all, period. That's not something we can rely on. For C++ libraries that expect RAII, that's what PointerScope is for.
Hello,
We've observed an issue wherein a reference to an internal member variable appears to become dangling after the class that contains that member is garbage-collected.
Question
Can references returned by
@ByRef
-annotated functions become dangling? Is there a way to prevent the reference from becoming dangling, or to instruct javacpp to make a copy of the underlying object?Here, VecVecR and GetNumbers are wrapped types. obj.nums() would return a const reference in C++. The java declaration of
nums()
is annotated with@ByRef
. Full definitions are provided below. On the C++ side of things,GetNumbers
is held by aunique_ptr
toGetNumbersI
.Definitions
Here,
GetNumbers
is a wrapper for a C++ class, where thenums()
function returns a const reference. This reference points to an internal member variable.Is it possible for an instance of
GetNumbers
to be garbage-collected while another variable holds onto the object returned bynums()
?We have a class with a method that returns a vector by const reference:
Source file:
This produces the following class:
Sample code causing crash
Here is roughly the code that causes the issue:
When a line of code that references
obj
is appended to the above, the crash goes away:The text was updated successfully, but these errors were encountered: