I am running calling a native function in Kotlin that takes a Unix file descriptor as a parameter. After the native function runs for a few minutes it report EBADF.
The code looks something like
class A(val file: ParcelFileDescriptor) : AutoCloseable {
private var fileDes: Int = -1
private external fun longRunningNativeFn(fd : Int) : FnResult
init {
fileDes = file.fd
}
fun process() : FnResult {
longRunningNativeFn(fileDes)
}
override fun close {
}
}
The file object passed into the constructor is not held anywhere else.
My working theory is that since file is only used in the init block, file then becomes a candidate for garbage collection so after a few minutes when the garbage collector kicks in, the file object calls close resulting in the native code getting a bad file descriptor.
So
is this theory correct?
If so what determines the lifetime of parameters in the constructor?
Does adding file.close() to the close function extend the lifetime of file for the duration of the class?
Note after adding the file.close(), I am no longer getting the BADF in my native code. Even though as #Ivo points out adding val to the primary constructor makes file a class member, the JRE might be smart enough to see nothing is using file and garbage collect it early since it needs to stick around until close is called
It's not merely a parameter of the constructor. You defined it as a property by writing val in front of it. You can access it throughout the entire lifetime of the instance. If you only want to have it as parameter you need to leave out the val like
class A(file: ParcelFileDescriptor) : AutoCloseable {
As for the lifetime if you write it like that, I personally don't know but I assume it gets garbage collected after the last init block but that's just a guess. And of course it also matters whether there are other references to that object outside of that class. I also have no idea why that EBADF happens
Related
What I can understand from google documentation is that we can use inline keyword to enhance the performance and reduce the memory allocation on runtime in case of high order function but why in this case we are inlining a variable
#PublishedApi
internal inline val <T : Any> T.loggingTag: String
get() {
val tag = this::class.java.name.substringAfterLast(".")
if (tag.contains("$")) {
return tag.substringBefore("$")
}
return tag
}
in case you are curious the logging tag variable is used in an inline function
inline fun <reified T : Any> T.errorLog(error: Throwable? = null, message: String? = null) {
errorLog(loggingTag, error, message)
}
also the errorLog function inlined even it doesn't take an other function as a parameters does anyone able to explain for me this ?
inline fun errorLog(tag: String, error: Throwable? = null, message: String? = null) {
Timber.tag(tag).e(error, message)
}
That val isn't a variable. It's a property. If you see val or var outside of a function, it's a property, not a variable.
Properties have getter functions. In your example, the getter function is what is being marked as inline.
There are two main reasons to use inline functions:
In a higher order function, it avoids allocating a function object to represent the function parameter (lambda or function reference) being passed to it. It also allows lambdas that are passed to use keywords that are normally restricted to local use, such as return, break, and continue.
It is necessary for reified generics. If a function needs to be able to inspect one of its generic types, the type needs to be marked as reified, which in turn requires the function to be marked inline.
Generally, you want to avoid using inline if a function doesn't fit one of the above cases, because actual function calls themselves are rather trivial, and if you inline a function that is used frequently (the only kind of function you would want to be optimized), then its code is going to be repeated everywhere it's used in your compiled app, increasing the size of the app.
An exception might be if the inline function contains only one function call, so it's not really increasing code size.
I do not see any reason the inline keyword is needed for the extension property in your first block of code. It is not a higher-order function, and it is a multi-line function. I also don't see why it is defined as a generic function, since the type T is not used for anything inside the function. I think I would define it as:
internal val Any.loggingTag: String
Also, in your second block of code, I don't see any reason why there is a generic type, since it is not used in that function. It could be defined as:
fun Any.errorLog(error: Throwable? = null, message: String? = null) {
The third block of code doesn't benefit much from inlining either. It's not a higher-order function. If function call overhead is that much of an issue for performance, it would make more sense to fork Timber and rewrite how it creates tags, because using custom temporary tags like that in Timber involves a few method calls under the hood.
The inline keyword is used to make functions inline, meaning that when a function is called, its body is copied and pasted into the caller's code instead of making a function call. This allows for reduced execution time, as there is no need to jump to another function and back. Inline functions can also be used to reduce code size and improve readability.
So currently I have a Dao with a function that emits a Flow<>
#Query("SELECT * FROM ${Constants.Redacted}")
fun loadAllContacts(): Flow<List<Redacted>>
I am calling this from a repository like so
val loadAllContacts: Flow<List<Redacted>> = contactDao.loadAllContacts()
I am injecting the repository into the viewModel's constructor, and then at the top of my viewModel I have a val like so
val contacts: LiveData<List<Redacted>> = contactRepository.loadAllContacts.asLiveData()
Which is being observed in my Activity like so
viewModel.contacts.observe(this) { contacts ->
viewModel.onContactsChange(contacts)
}
My thinking is that the Flow is converted to a LiveData, and then I can observe this LiveData from my activity and kick off this function to actually update the viewModel upon the data being updated.
For now onContactsChange just looks like
fun onContactsChange(list: List<Redacted>) {
Timber.i("VIEW UPDATE")
}
The problem is that I only see this Timber log upon opening the activity, and never again. I verified that data IS going into my database, and I verified that an insert occurred successfully while the activity & viewModel are open. But I never see the log from onContactsChange again. When I close the activity, and reopen it, I do see my new data, so that is another reason I know my insert is working correctly.
I would like to add that I am using a single instance (singleton) of my repository, and I think I can verify this by the fact that I can see my data at all, at least when the view is first made.
Figured it out:
Note: If your app runs in a single process, you should follow the singleton design pattern when instantiating an AppDatabase object. Each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances within a single process.
If your app runs in multiple processes, include enableMultiInstanceInvalidation() in your database builder invocation. That way, when you have an instance of AppDatabase in each process, you can invalidate the shared database file in one process, and this invalidation automatically propagates to the instances of AppDatabase within other processes.
It's a little bit hard to follow your question, but I think I see the overall problem with your Flow object not updating the way you want it too.
Following this quick tutorial, it seems that first you should declare your Flow object inside your Repository the same way you're already doing
val loadAllContacts: Flow<List<Redacted>> = contactDao.loadAllContacts()
and have your VM 'subscribe' to it by using the collect coroutine which would then allow you to dump all this data into a MutableLiveData State
data class YourState(..)
val state = MutableLiveData<YourState>()
init {
contactRepository.loadAllContacts().collect {
if (it.isNotEmpty()) {
state.postValue(YourState(
...
)
}
}
}
that your Activity/Fragment could then observe for changes
viewModel.state.observe(.. { state ->
// DO SOMETHING
})
P.S. The tutorial also mentions that because of how Dao's work, you might be getting updates for even the slightest of changes, but that you can use the distinctUntilChanged() Flow extension function to get more specific results.
I am using an Observable field in a ViewModel. When the Observable field gets updated, I change the UI visibility.
This can be done either done by
object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
}
}
remove the callback in ondestroy.
or
directly mapping in XML like #{} using two-way binding.
Now the question is how do I remove the listener if using two-way binding? I know the Livedata can be a replacement for this.
I am not sure regarding which memory leak you are talking.
Memory leak in Java occur when one object exists long period of time and it contains strong references to other objects that should not be used anymore, thus should be destroyed by GC, but still persist because of that strong reference.
In Android specifically memory leaks usually occur when some long lasting object stores strong reference to an Activity (or in some cases Fragment). All the other memory leaks in android are not so impactful(except the ones with bitmaps - but it is a completely different topic)
So let us return to the data binding with an ObservableField and its callbacks inside the ViewModel or two way data binding via #={}. In most of the cases there will be no memory leak in both of those cases. To understand why - you will need to understand how does Android framework operates with UI and also understand now does view data binding works. So what happens when you are creating a callback via either ObservableField and callback or with #={}
When you write
val someField: ObservabaleField = ObservableFiled<String>("someText")
val someCallback = object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
}
}
someField.addOnPropertyChangedCallback(someCallback)
// and in the layout
android:text="#={viewModel.someField}"
In the generated file it does something like this
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, viewModelSomeFieldGet);
#Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
switch (localFieldId) {
case 0 :
//...
return onChangeViewModelSomeOtherStuff(object, fieldId);
case 1 :
return onChangeViewModelSomeField((androidx.databinding.ObservableField<java.lang.String>) object, fieldId);
}
return false;
}
As you can see there is no context neither activity or fragment leaks since there is no strong reference to them stored anywhere. There is no references to context, activity or fragment in your ViewModel either(I hope!). Moreover it works the other way around - ui stores link to the ViewModel in the binding implementation thus our ViewModel may be leaking. It is rear case since the UI of an Activity or a Fragment usually gets destroyed along with its ActivityBindingImpl or FragmentBindingImpl bindings but...
To be sure you have manual way to clear references: in either Activity' onDestroy or Fragment' onDestroyView call
clearFindViewByIdCache()
binding.unbind()
binding = null
// if you store view link in your viewModel(which is bad and may cause leaks) this is the perfect place to nullify it
viewModel.view = null
Also to handle binding auto clearing you may use AutoClearedValue
the actual usage may look like(if you don't care about its type)
override var binding: ViewDataBinding? by autoCleared()// that is all - no need of onDestroy or onDestroyView
Edit
If you want to manually unregister all the callbacks from your ObservableFields you can do it. The best way to do it is in onCleared() method of ViewModel. You should call observableField.removeOnPropertyChangedCallback(callback) to handle the stuff. It will look like this considering ObservableField and callback declarations above:
class MyViewModel: ViewModel{
//ObservableField and callback declarations
...
override void onCleared(){
someField.removeOnPropertyChangedCallback(someCallback)
}
}
Edit end
This all things I've just described ensures absence of memory leaks while using ObservableFields and view data bindings. It is all about a correct implementation. Of course you can implement it with leaks, but you can implement it without ones.
Comment if something is still unclear - I will try to expand the answer.
A bit more info about Fragment dependent leaks here
Hope it helps.
You can do that using removeOnPropertyChangedCallback function in ViewModel class. Here is how your ViewModel would look like:
abstract class ObservableViewModel(app: Application): AndroidViewModel(app), Observable {
#delegate:Transient
private val mCallBacks: PropertyChangeRegistry by lazy { PropertyChangeRegistry() }
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
mCallBacks.add(callback)
}
override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
mCallBacks.remove(callback)
}
fun notifyChange() {
mCallBacks.notifyChange(this, 0)
}
fun notifyChange(viewId:Int){
mCallBacks.notifyChange(this, viewId)
}
}
removeOnPropertyChangedCallback never gets called?
This actually does
get called, eventually and periodically, by the Data Binding framework
to clean listeners that have been collected. It’s likely however, that
your ViewModel will still have some callbacks registered when it is
destroyed, and this is okay. The Data Binding framework uses weak
references for the observers and it’s not required that they be
unregistered before the ViewModel is destroyed. This won’t cause any
memory leaks.
With that said, if you rotate the phone rapidly, several times in a
row, while on the same screen. You’ll notice
ObservableViewModel.addOnPropertyChangedCallBack is called several
times and if you look inside the source for
android.databinding.ViewDataBinding, you’ll see the observer count
does rise each time.
This is where the periodic removal comes in. If you use the app long
enough, rotate a few times, and have a breakpoint set on
ObservableViewModel.removeOnPropertyChangedCallback. You’ll see that
it is called periodically to clean up old observers and if you look up
the call stack you can find more detail about where that comes from,
how it’s triggered, etc.
You can track more at: https://caster.io/lessons/android-mvvm-pattern-with-architecture-component-viewmodels.
Hope this help you!!
I recently made the transition from iOS/Swift to Androi/Kotlin. I am using a object for encapsulating Analytics functionality (as I did in Swift):
Object Analytics{
var connection: AnalyticsConnection? = null
fun sendEvent(name: String)...
init {
connection = //allocate here
}
}
I heard (one of our Android devs mentioned it) that in the latest version of kotlin the var connection could actually loose it value at some point spontanically? I find this very weird, is this true? It seams that vars at global scope get cleared out at some point?
It should not lose the values it contains because when you create a new class as an object you create it as a thread-safe singleton.
Which means unless you directly change the value somewhere else, the value should stay the same as the original value.
That's all in case your application is still alive, in case your application is killed/ destroyed the whole class would also be destroyed with it.
In the last year I've become a mobile developer and a functional programming admirer.
In each of the mobile arenas there are components with lifecycle methods that make up the meat of the app. The following will use Android and Kotlin as examples, but the same applies to iOS and Swift.
In Android, there are Activity's with lifecycle methods like onCreate(). You might also define a function, onButtonClicked(), which will do exactly what the name describes.
For the purposes of the question, let's say there's a variable defined in onCreate() that is used in a button click handler onButtonClickedPrintMessageLength() (This is usually the case - onCreate() is essentially Activity's setup method).
The example class would look like this:
class ExampleActivity: Activity() {
var savedStateMessage: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
savedStateMessage = "Hello World!"
}
fun onButtonClickedPrintMessageLength() {
System.out.println(savedStateMessage?.length)
}
}
Notice the declaration of savedStateMessage as a String? (nullable string) and the use of ?. (null safe call). These are required because the compiler cant guarantee that onCreate() will be called before onButtonClickedPrintMessageLength(). As developers though, we know that onCreate will always be called first* **.
My question is how can I tell the compiler about the guaranteed order of these methods and eliminate the null checking behavior?
* I suppose it's possible to new up our ExampleActivity and call onButtonClickedPrintMessageLength() directly, thus sidestepping the Android framework and lifecycle methods, but the compiler/JVM would likely run into an error before anything interesting happened.
** The guarantee that onCreate is called first is provided by the Android framework, which is an external source of truth and might break/function differently in the future. Seeing that all Android apps are based on this source of truth though, I believe it's safe to trust.
Although this won't answer your actual question, in Kotlin you can use lateinit to tell the compiler that you'll initialize a var at a later point in time:
lateinit var savedStateMessage: String
You'll get a very specific UninitializedPropertyAccessException if you try to use this variable before initializing it. This feature is useful in use cases like JUnit, where you'd usually initialize variables in #Before-annotated method, and Android Activitys, where you don't have access to the constructor and initialize stuff in onCreate().
As mentioned in another answer, lateinit is available as an option to defer initialization to a later point in a guaranteed lifecycle. An alternative is to use a delegate:
var savedStateMessage: String by Delegates.notNull()
Which is equivalent, in that it will report an error if you access the variable before initializing it.
In Swift this is where you would use an implicitly-unwrapped Optional:
class Example: CustomStringConvertible {
var savedStateMessage: String! // implicitly-unwrapped Optional<String>
var description: String { return savedStateMessage }
init() {
savedStateMessage = "Hello World!"
}
}
print(Example()) // => "Hello World!\n"
By using the operator ! at the end of String in the second line of the example you are promising that the variable will be set before it can be used. This is accomplished in the init method of the example. It's still an Optional but code can treat it as a String since it will be automatically unwrapped before each use. You must take care that the variable is never set to nil when it might be accessed or a runtime exception may be generated.