musikr: fix memory leaks

This commit is contained in:
Alexander Capehart 2025-01-18 17:19:03 -07:00
parent 3aae8ea534
commit 1bf44eba91
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 76 additions and 49 deletions

View file

@ -23,12 +23,11 @@
// TODO: Handle stream exceptions
JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inputStream(
inputStream) {
if (!env->IsInstanceOf(inputStream,
env->FindClass("org/oxycblt/musikr/metadata/NativeInputStream"))) {
throw std::runtime_error("oStream is not an instance of TagLibOStream");
}
jclass inputStreamClass = env->FindClass(
"org/oxycblt/musikr/metadata/NativeInputStream");
if (!env->IsInstanceOf(inputStream, inputStreamClass)) {
throw std::runtime_error("oStream is not an instance of TagLibOStream");
}
inputStreamReadBlockMethod = env->GetMethodID(inputStreamClass, "readBlock",
"(J)[B");
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass, "isOpen",
@ -57,7 +56,7 @@ TagLib::FileName JVMInputStream::name() const {
TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
auto data = (jbyteArray) env->CallObjectMethod(inputStream,
inputStreamReadBlockMethod, length);
inputStreamReadBlockMethod, static_cast<jlong>(length));
if (data == nullptr) {
throw std::runtime_error("Failed to read block, see logs");
}
@ -66,6 +65,7 @@ TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
TagLib::ByteVector byteVector(reinterpret_cast<const char*>(dataBytes),
dataLength);
env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT);
env->DeleteLocalRef(data);
return byteVector;
}

View file

@ -188,10 +188,11 @@ jobject JVMMetadataBuilder::build() {
"org/oxycblt/musikr/metadata/Properties");
jmethodID propertiesInit = env->GetMethodID(propertiesClass, "<init>",
"(Ljava/lang/String;JII)V");
jstring jmimeType = env->NewStringUTF(mimeType.data());
jobject propertiesObj = env->NewObject(propertiesClass, propertiesInit,
env->NewStringUTF(mimeType.data()),
(jlong) properties->lengthInMilliseconds(), properties->bitrate(),
properties->sampleRate());
jmimeType, (jlong) properties->lengthInMilliseconds(),
properties->bitrate(), properties->sampleRate());
env->DeleteLocalRef(jmimeType);
env->DeleteLocalRef(propertiesClass);
jclass metadataClass = env->FindClass(
@ -211,6 +212,11 @@ jobject JVMMetadataBuilder::build() {
}
jobject metadataObj = env->NewObject(metadataClass, metadataInit, id3v2Map,
xiphMap, mp4Map, coverArray, propertiesObj);
env->DeleteLocalRef(propertiesObj);
env->DeleteLocalRef(metadataClass);
env->DeleteLocalRef(coverArray);
env->DeleteLocalRef(id3v2Map);
env->DeleteLocalRef(xiphMap);
env->DeleteLocalRef(mp4Map);
return metadataObj;
}

View file

@ -52,57 +52,78 @@ JVMTagMap::~JVMTagMap() {
env->DeleteLocalRef(arrayListClass);
}
void JVMTagMap::add_id(TagLib::String id, TagLib::String value) {
env->CallVoidMethod(tagMap, tagMapAddIdSingleMethod,
env->NewStringUTF(id.toCString(true)),
env->NewStringUTF(value.toCString(true)));
void JVMTagMap::add_id(const TagLib::String id, const TagLib::String value) {
jstring jid = env->NewStringUTF(id.toCString(true));
jstring jvalue = env->NewStringUTF(value.toCString(true));
env->CallVoidMethod(tagMap, tagMapAddIdSingleMethod, jid, jvalue);
env->DeleteLocalRef(jid);
env->DeleteLocalRef(jvalue);
}
void JVMTagMap::add_id(TagLib::String id, TagLib::StringList value) {
jobject arrayList = env->NewObject(arrayListClass, arrayListInitMethod);
for (auto &item : value) {
env->CallBooleanMethod(arrayList, arrayListAddMethod,
env->NewStringUTF(item.toCString(true)));
void JVMTagMap::add_id(const TagLib::String id,
const TagLib::StringList values) {
jstring jid = env->NewStringUTF(id.toCString(true));
jobject jvalues = env->NewObject(arrayListClass, arrayListInitMethod);
for (auto &item : values) {
jstring jvalue = env->NewStringUTF(item.toCString(true));
env->CallBooleanMethod(jvalues, arrayListAddMethod, jvalue);
env->DeleteLocalRef(jvalue);
}
env->CallVoidMethod(tagMap, tagMapAddIdListMethod,
env->NewStringUTF(id.toCString(true)), arrayList);
env->CallVoidMethod(tagMap, tagMapAddIdListMethod, jid, jvalues);
env->DeleteLocalRef(jid);
}
void JVMTagMap::add_custom(TagLib::String description, TagLib::String value) {
env->CallVoidMethod(tagMap, tagMapAddCustomSingleMethod,
env->NewStringUTF(description.toCString(true)),
env->NewStringUTF(value.toCString(true)));
void JVMTagMap::add_custom(const TagLib::String description,
const TagLib::String value) {
jstring jdescription = env->NewStringUTF(description.toCString(true));
jstring jvalue = env->NewStringUTF(value.toCString(true));
env->CallVoidMethod(tagMap, tagMapAddCustomSingleMethod, jdescription,
jvalue);
env->DeleteLocalRef(jdescription);
env->DeleteLocalRef(jvalue);
}
void JVMTagMap::add_custom(TagLib::String description,
TagLib::StringList value) {
jobject arrayList = env->NewObject(arrayListClass, arrayListInitMethod);
for (auto &item : value) {
env->CallBooleanMethod(arrayList, arrayListAddMethod,
env->NewStringUTF(item.toCString(true)));
void JVMTagMap::add_custom(const TagLib::String description,
const TagLib::StringList values) {
jstring jid = env->NewStringUTF(description.toCString(true));
jobject jvalues = env->NewObject(arrayListClass, arrayListInitMethod);
for (auto &item : values) {
jstring jvalue = env->NewStringUTF(item.toCString(true));
env->CallBooleanMethod(jvalues, arrayListAddMethod, jvalue);
env->DeleteLocalRef(jvalue);
}
env->CallVoidMethod(tagMap, tagMapAddCustomListMethod,
env->NewStringUTF(description.toCString(true)), arrayList);
env->CallVoidMethod(tagMap, tagMapAddCustomListMethod, jid, jvalues);
env->DeleteLocalRef(jid);
env->DeleteLocalRef(jvalues);
}
void JVMTagMap::add_combined(TagLib::String id, TagLib::String description,
TagLib::String value) {
env->CallVoidMethod(tagMap, tagMapAddCombinedSingleMethod,
env->NewStringUTF(id.toCString(true)),
env->NewStringUTF(description.toCString(true)),
env->NewStringUTF(value.toCString(true)));
void JVMTagMap::add_combined(const TagLib::String id,
const TagLib::String description, const TagLib::String value) {
jstring jid = env->NewStringUTF(id.toCString(true));
jstring jdescription = env->NewStringUTF(description.toCString(true));
jstring jvalue = env->NewStringUTF(value.toCString(true));
env->CallVoidMethod(tagMap, tagMapAddCombinedSingleMethod, jid,
jdescription, jvalue);
env->DeleteLocalRef(jid);
env->DeleteLocalRef(jdescription);
env->DeleteLocalRef(jvalue);
}
void JVMTagMap::add_combined(TagLib::String id, TagLib::String description,
TagLib::StringList value) {
jobject arrayList = env->NewObject(arrayListClass, arrayListInitMethod);
for (auto &item : value) {
env->CallBooleanMethod(arrayList, arrayListAddMethod,
env->NewStringUTF(item.toCString(true)));
void JVMTagMap::add_combined(const TagLib::String id,
const TagLib::String description, const TagLib::StringList values) {
jstring jid = env->NewStringUTF(id.toCString(true));
jstring jdescription = env->NewStringUTF(description.toCString(true));
jobject jvalues = env->NewObject(arrayListClass, arrayListInitMethod);
for (auto &item : values) {
jstring jvalue = env->NewStringUTF(item.toCString(true));
env->CallBooleanMethod(jvalues, arrayListAddMethod, jvalue);
env->DeleteLocalRef(jvalue);
}
env->CallVoidMethod(tagMap, tagMapAddCombinedListMethod,
env->NewStringUTF(id.toCString(true)),
env->NewStringUTF(description.toCString(true)), arrayList);
env->CallVoidMethod(tagMap, tagMapAddCombinedListMethod, jid, jdescription,
jvalues);
env->DeleteLocalRef(jid);
env->DeleteLocalRef(jdescription);
env->DeleteLocalRef(jvalues);
}
jobject JVMTagMap::getObject() {

View file

@ -33,15 +33,15 @@ public:
JVMTagMap& operator=(const JVMTagMap&) = delete;
void add_id(TagLib::String id, TagLib::String value);
void add_id(TagLib::String id, TagLib::StringList value);
void add_id(TagLib::String id, TagLib::StringList values);
void add_custom(TagLib::String description, TagLib::String value);
void add_custom(TagLib::String description, TagLib::StringList value);
void add_custom(TagLib::String description, TagLib::StringList values);
void add_combined(TagLib::String id, TagLib::String description,
TagLib::String value);
void add_combined(TagLib::String id, TagLib::String description,
TagLib::StringList value);
TagLib::StringList values);
jobject getObject();