安卓逆向之NDK内存管理

ops/2024/9/20 2:04:05/ 标签: android

一:内存管理

在 JNI 中,内存管理是一个重要的主题,尤其是在处理 Java 和 C++ 之间的对象时。以下是一些关键点和最佳实践,以确保有效的内存管理。

1. 局部引用管理

  • 局部引用:在 JNI 中,调用 Java 方法时会创建局部引用。这些引用在方法返回后会被自动释放,但在长时间运行的本地方法中,可能会导致局部引用表溢出。
  • 手动删除:使用 DeleteLocalRef 手动删除不再需要的局部引用。
jobject localRef = env->NewObject(...);
// 使用 localRef
env->DeleteLocalRef(localRef); // 手动删除

2. 全局引用

  • 全局引用:如果需要在多个 JNI 调用之间共享对象,可以创建全局引用。全局引用在整个应用程序生命周期内有效,直到显式删除。
  • 创建全局引用:使用 NewGlobalRef 创建全局引用。
  • 删除全局引用:使用 DeleteGlobalRef 删除全局引用。
jobject globalRef = env->NewGlobalRef(localRef);
// 使用 globalRef
env->DeleteGlobalRef(globalRef); // 手动删除

3. 字符串和数组管理

  • 字符串:使用 GetStringUTFChars 获取 C 字符串时,确保在使用后调用 ReleaseStringUTFChars 释放。
jstring jstr = ...;
const char *cstr = env->GetStringUTFChars(jstr, nullptr);
// 使用 cstr
env->ReleaseStringUTFChars(jstr, cstr); // 释放
  • 数组:在处理 Java 数组时,使用 Get<PrimitiveType>ArrayElements 获取元素,并在使用后调用相应的释放函数。
jintArray intArray = ...;
jint *elements = env->GetIntArrayElements(intArray, nullptr);
// 使用 elements
env->ReleaseIntArrayElements(intArray, elements, 0); // 释放

4. 避免内存泄漏

  • 检查返回值:在调用 JNI 函数时,检查返回值是否为 nullptr,以避免对空指针的操作。
  • 适时释放:确保在不再需要对象时及时释放引用,避免内存泄漏。

5. 使用 CallNonvirtualVoidMethod

当需要调用父类的方法时,可以使用 CallNonvirtualVoidMethod。以下是如何使用它的示例:

示例代码

假设有一个 Java 类 Parent 和一个子类 Child,我们希望从 C++ 中调用 Parent 的方法。

// Parent.java
package com.example.yourapp;public class Parent {public void greet() {System.out.println("Hello from Parent!");}
}// Child.java
package com.example.yourapp;public class Child extends Parent {public void greet() {System.out.println("Hello from Child!");}
}

C++ 代码

#include <jni.h>
#include <android/log.h>#define LOG_TAG "NativeExample"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_callParentGreet(JNIEnv *env, jobject childObj) {// 获取 Parent 类的引用jclass parentClass = env->FindClass("com/example/yourapp/Parent");if (parentClass == nullptr) {LOGI("Failed to find Parent class");return;}// 获取 greet 方法的 IDjmethodID greetMethod = env->GetMethodID(parentClass, "greet", "()V");if (greetMethod == nullptr) {LOGI("Failed to find greet method");return;}// 调用 Parent 的 greet 方法env->CallNonvirtualVoidMethod(childObj, parentClass, greetMethod);// 释放局部引用env->DeleteLocalRef(parentClass);
}

代码解释

  1. 获取类引用:使用 FindClass 获取父类 Parent 的引用。
  2. 获取方法 ID:使用 GetMethodID 获取 greet 方法的 ID。
  3. 调用父类方法:使用 CallNonvirtualVoidMethod 调用父类的 greet 方法。
  4. 释放局部引用:确保释放所有局部引用以避免内存泄漏。

1.局部引用

大多数的jni函数,调用以后返回的结果都是局部引用

因此env→NewLocalRef基本不用

一个函数内的局部引用数量是有限的,在早期的安卓系统中,体现的更未明显,当函数内需要大量局部引用时,比如大循环中,最好及时删除不用的局部引用,可以使用env→DeleLocalRef来删除局部引用.

局部引用是 JNI 中的重要概念,它们用于管理从 Java 代码中创建的对象的生命周期。理解局部引用的工作原理对于确保在 JNI 中有效的内存管理至关重要。

什么是局部引用?

局部引用是在 JNI 方法中创建的对象引用,这些引用在方法执行期间有效。当 JNI 方法返回时,这些局部引用会被自动释放。局部引用的作用范围仅限于创建它们的 JNI 方法。

创建局部引用

局部引用通常通过 JNI 函数创建,例如:

  • NewObject:创建一个新的 Java 对象。
  • NewStringUTF:创建一个新的字符串对象。
  • GetObjectArrayElement:从对象数组中获取元素。

示例

jclass myClass = env->FindClass("com/example/MyClass");
jmethodID constructor = env->GetMethodID(myClass, "<init>", "()V");
jobject myObject = env->NewObject(myClass, constructor);

在这个例子中,myObject 是一个局部引用,指向新创建的 Java 对象。

管理局部引用

虽然局部引用在方法返回时会被自动释放,但在某些情况下(例如长时间运行的本地方法),可能会导致局部引用表溢出。因此,适当管理局部引用非常重要。

1. 手动删除局部引用

在不再需要某个局部引用时,可以使用 DeleteLocalRef 手动删除它,以释放内存:

env->DeleteLocalRef(myObject);

2. 避免局部引用溢出

如果在一个 JNI 方法中创建了大量的局部引用,可能会导致局部引用表溢出。可以使用以下方法来避免这种情况:

  • 定期删除局部引用:在循环中创建局部引用时,定期调用 DeleteLocalRef
  • 使用 PushLocalFramePopLocalFrame:这两个方法允许你在局部引用帧中管理局部引用的生命周期。
env->PushLocalFrame(16); // 创建一个局部引用帧,最多可以存储 16 个局部引用
jobject localRef = env->NewObject(...);
// 使用 localRef
env->PopLocalFrame(nullptr); // 释放局部引用帧中的所有引用

例子:局部引用的使用

以下是一个简单的例子,展示如何在 JNI 中使用局部引用:

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_exampleMethod(JNIEnv *env, jobject obj) {jclass stringClass = env->FindClass("java/lang/String");if (stringClass == nullptr) {return; // 处理错误}jmethodID constructor = env->GetMethodID(stringClass, "<init>", "(Ljava/lang/String;)V");jstring jstr = env->NewStringUTF("Hello from JNI!");jobject myStringObject = env->NewObject(stringClass, constructor, jstr);// 使用 myStringObject// ...// 释放局部引用env->DeleteLocalRef(jstr);env->DeleteLocalRef(myStringObject);env->DeleteLocalRef(stringClass);
}

总结

局部引用是 JNI 中管理 Java 对象的基本机制。正确使用和管理局部引用可以避免内存泄漏和局部引用表溢出。通过手动删除不再需要的引用和使用局部引用帧,可以有效地控制内存使用。

2.局部引用相关的其他函数

env→EnsureLocalcapacity(num),判断是否有足够的局部引用可以使用,足够则返回0,需要大量使用局部引用时,手动删除太麻烦,可以使用一下俩个函数来批量管理局部引用.

env→PushLocalFrame(num)

env→PopLocalFrame(nullptr)

在 JNI 中,除了基本的局部引用管理函数 NewLocalRefDeleteLocalRef 外,还有一些其他相关的函数,可以帮助管理和优化局部引用的使用。以下是一些重要的局部引用相关函数及其用途:

1. PushLocalFramePopLocalFrame

  • PushLocalFrame:创建一个新的局部引用帧,可以在该帧中存储局部引用。局部引用将在帧被弹出时自动释放。
  • PopLocalFrame:释放局部引用帧中的所有局部引用。

示例

env->PushLocalFrame(10); // 创建一个局部引用帧,最多可以存储 10 个局部引用jobject localRef1 = env->NewObject(...);
jobject localRef2 = env->NewObject(...);
// 使用 localRef1 和 localRef2env->PopLocalFrame(nullptr); // 释放局部引用帧中的所有引用

2. NewLocalRef

  • NewLocalRef:创建一个新的局部引用,指向现有的对象。它可以用于将全局引用或其他局部引用转换为局部引用。

示例

jobject globalRef = env->NewGlobalRef(someObject);
jobject localRef = env->NewLocalRef(globalRef); // 将全局引用转换为局部引用
// 使用 localRef
env->DeleteLocalRef(localRef);
env->DeleteGlobalRef(globalRef); // 释放全局引用

3. GetObjectArrayElement

  • GetObjectArrayElement:从 Java 对象数组中获取元素,返回的对象是局部引用。

示例

jobjectArray objectArray = ...; // 假设这是一个有效的 jobjectArray
jobject element = env->GetObjectArrayElement(objectArray, index);
// 使用 element
env->DeleteLocalRef(element); // 释放局部引用

4. SetObjectArrayElement

  • SetObjectArrayElement:将一个对象设置到 Java 对象数组中的指定索引。传入的对象可以是局部引用。

示例

jobjectArray objectArray = ...; // 假设这是一个有效的 jobjectArray
jobject newElement = env->NewObject(...); // 创建一个新的对象
env->SetObjectArrayElement(objectArray, index, newElement);
env->DeleteLocalRef(newElement); // 释放局部引用

5. CallObjectMethod

  • CallObjectMethod:调用对象的方法并返回一个对象,返回的对象是局部引用。

示例

jobject result = env->CallObjectMethod(someObject, methodID);
// 使用 result
env->DeleteLocalRef(result); // 释放局部引用

6. GetMethodIDGetFieldID

  • GetMethodIDGetFieldID:虽然这些函数本身不创建局部引用,但它们返回的方法和字段 ID 可以用于后续操作,调用这些方法或访问字段时会产生局部引用。

示例

jclass clazz = env->FindClass("com/example/MyClass");
jmethodID methodID = env->GetMethodID(clazz, "myMethod", "()V");
jfieldID fieldID = env->GetFieldID(clazz, "myField", "Ljava/lang/String;");

7. GetStringUTFCharsReleaseStringUTFChars

  • GetStringUTFChars:获取 Java 字符串的 C 字符串表示,返回的指针需要在使用后释放。
  • ReleaseStringUTFChars:释放通过 GetStringUTFChars 获取的 C 字符串。

示例

jstring jstr = ...;
const char *cstr = env->GetStringUTFChars(jstr, nullptr);
// 使用 cstr
env->ReleaseStringUTFChars(jstr, cstr); // 释放

3.全局引用


在 JNI 中,全局引用是一种特殊的引用类型,用于在 C++ 代码中持有 Java 对象的引用。与局部引用不同,全局引用在 JNI 方法返回后仍然有效,直到显式删除。全局引用的主要用途是允许跨多个 JNI 方法或线程使用 Java 对象。

什么是全局引用?

全局引用是在 JNI 中创建的对象引用,可以在整个应用程序生命周期内使用。它们的主要特性包括:

  • 持久性:全局引用在创建后不会自动释放,直到调用 DeleteGlobalRef 显式删除。
  • 跨方法和线程:全局引用可以在不同的 JNI 方法和线程之间共享。

创建全局引用

要创建全局引用,可以使用 NewGlobalRef 函数。以下是创建全局引用的示例:

jobject localRef = env->NewObject(...); // 创建一个局部引用
jobject globalRef = env->NewGlobalRef(localRef); // 创建全局引用
env->DeleteLocalRef(localRef); // 可以安全地删除局部引用

删除全局引用

全局引用在不再需要时必须显式删除,以避免内存泄漏。使用 DeleteGlobalRef 来删除全局引用:

env->DeleteGlobalRef(globalRef); // 删除全局引用

使用全局引用

全局引用可以在 JNI 方法中安全地使用,以下是一个使用全局引用的示例:

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_useGlobalRef(JNIEnv *env, jobject obj) {// 创建一个局部引用并转换为全局引用jclass myClass = env->FindClass("com/example/MyClass");jmethodID constructor = env->GetMethodID(myClass, "<init>", "()V");jobject localRef = env->NewObject(myClass, constructor);jobject globalRef = env->NewGlobalRef(localRef);env->DeleteLocalRef(localRef); // 删除局部引用// 使用全局引用jmethodID someMethod = env->GetMethodID(myClass, "someMethod", "()V");env->CallVoidMethod(globalRef, someMethod);// 删除全局引用env->DeleteGlobalRef(globalRef);
}

全局引用的注意事项

  1. 内存管理:全局引用不会自动释放,因此必须在不再需要时手动删除,以避免内存泄漏。
  2. 线程安全:全局引用可以在多个线程中使用,但需要确保在多线程环境中对全局引用的访问是线程安全的。
  3. 局部引用与全局引用的选择:如果只需在单个 JNI 方法中使用对象,使用局部引用即可。如果需要在多个方法或线程之间共享对象,则应使用全局引用。

例子:全局引用管理

以下是一个完整的示例,展示如何在 JNI 中创建和使用全局引用:

#include <jni.h>
#include <android/log.h>#define LOG_TAG "NativeExample"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_exampleMethod(JNIEnv *env, jobject obj) {// 创建一个局部引用jclass myClass = env->FindClass("com/example/MyClass");jmethodID constructor = env->GetMethodID(myClass, "<init>", "()V");jobject localRef = env->NewObject(myClass, constructor);// 创建全局引用jobject globalRef = env->NewGlobalRef(localRef);env->DeleteLocalRef(localRef); // 删除局部引用// 调用方法jmethodID someMethod = env->GetMethodID(myClass, "someMethod", "()V");env->CallVoidMethod(globalRef, someMethod);// 删除全局引用env->DeleteGlobalRef(globalRef);
}

总结

全局引用在 JNI 中提供了一种持久的方式来管理 Java 对象,允许跨多个 JNI 方法和线程使用这些对象。正确管理全局引用至关重要,以避免内存泄漏和确保应用程序的稳定性。通过适当的创建和删除全局引用,可以有效地在 C++ 和 Java 之间进行交互。

4.弱全局引用

在 JNI 中,全局引用和弱全局引用是用于管理 Java 对象生命周期的两种重要引用类型。它们在内存管理、性能优化和避免内存泄漏方面具有不同的特性和使用场景。

全局引用

全局引用是 JNI 中一种特殊的引用类型,它可以在多个 JNI 调用之间共享,并在整个应用程序生命周期内有效。全局引用不会被垃圾回收器自动释放,直到显式删除。

创建全局引用

使用 NewGlobalRef 创建全局引用:

jobject globalRef = env->NewGlobalRef(localRef);

删除全局引用

使用 DeleteGlobalRef 删除全局引用:

env->DeleteGlobalRef(globalRef);

弱全局引用

弱全局引用(Weak Global Reference)是一种特殊的引用类型,它允许程序在不阻止对象被垃圾回收的情况下引用 Java 对象。弱全局引用在 Java 中的生命周期与普通全局引用不同,垃圾回收器可以在需要时回收弱全局引用指向的对象。

创建弱全局引用

使用 NewWeakGlobalRef 创建弱全局引用:

jobject weakGlobalRef = env->NewWeakGlobalRef(localRef);

删除弱全局引用

使用 DeleteWeakGlobalRef 删除弱全局引用:

env->DeleteWeakGlobalRef(weakGlobalRef);

使用弱全局引用的场景

  1. 避免内存泄漏:在某些情况下,使用弱全局引用可以防止强引用导致的内存泄漏。例如,当你想要缓存对象,但又不希望阻止它们被垃圾回收时,可以使用弱全局引用。
  2. 缓存对象:在某些情况下,可以使用弱全局引用缓存对象,以便在需要时访问,但不阻止对象被回收。
  3. 事件处理:在事件处理或回调机制中,使用弱全局引用可以避免循环引用的问题。

检查弱全局引用的有效性

由于弱全局引用在对象被垃圾回收后会变为 nullptr,因此在使用弱全局引用之前,应该检查它是否仍然有效。可以使用 IsSameObject 来检查弱全局引用是否指向一个有效的对象。

示例代码

以下是一个使用弱全局引用的示例:

extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_exampleMethod(JNIEnv *env, jobject obj) {// 创建一个局部引用jobject localRef = env->NewObject(...);// 创建弱全局引用jobject weakGlobalRef = env->NewWeakGlobalRef(localRef);// 删除局部引用env->DeleteLocalRef(localRef);// 检查弱全局引用是否有效if (weakGlobalRef != nullptr) {// 使用 weakGlobalRef// ...} else {// 对象已被垃圾回收}// 删除弱全局引用env->DeleteWeakGlobalRef(weakGlobalRef);
}

总结

弱全局引用在 JNI 中提供了一种灵活的方式来管理 Java 对象的生命周期。它们允许程序在不阻止对象被垃圾回收的情况下引用对象,从而帮助避免内存泄漏和循环引用。使用弱全局引用时,确保在使用之前检查其有效性,以避免访问已被回收的对象。


http://www.ppmy.cn/ops/113201.html

相关文章

【自动化测试】常见的自动化遍历工具以及如何选择合适的自动化遍历工具

引言 自动化遍历测试通常依赖于特定的工具来实现应用的自动操作和测试 文章目录 引言一、常见的自动化遍历工具1.1 Appium1.2 Selenium1.3 Calabash1.4 Robot Framework1.5 Espresso1.6 XCTest1.7 Macaca1.8 TestComplete1.9 UiAutomator1.10 总结 二、如何选择合适的自动化遍历…

Spring Boot- 数据库相关问题

Spring Boot 与数据库相关问题及其解决方案 1. 引言 Spring Boot简化了Java企业级应用的开发&#xff0c;尤其在与数据库交互方面提供了诸多便利。Spring Boot提供了多种数据库集成方案&#xff0c;涵盖关系型数据库&#xff08;如MySQL、PostgreSQL等&#xff09;与非关系型…

好用的ai写作有哪些?5个软件帮助你快速进行ai写作

好用的ai写作有哪些&#xff1f;5个软件帮助你快速进行ai写作 AI写作工具正变得越来越流行&#xff0c;能够帮助用户更快速、高效地完成各种写作任务&#xff0c;包括生成文章、写小说、改进语法等。以下是5个非常好用的AI写作软件&#xff0c;它们可以帮助你快速进行AI写作&a…

面试—多线程

目录 线程的创建方式 线程的生命周期 线程同步的方法 多线程内存可见性 线程安全问题 线程的创建方式 继承Therad类 定义一个类继承Therad类 重写run()方法&#xff08;线程实际执行的逻辑&#xff09; 创建类的对象&#xff0c;调用start()方法开启线程 实现Runnable接口…

云计算实训48——k8s环境搭建(详细版)

1.创建主机、设置ip、设置hostname 2.设置免密登录 # 生成私钥 [rootk8s-master ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa already exists. Overwrite (y/n)? y Enter passphr…

App结合3D形象的技术实现选择

在为App添加3D人物交互效果时&#xff0c;可以采用多种技术&#xff0c;具体选择取决于你的目标平台&#xff08;iOS、Android、跨平台&#xff09;以及项目的复杂性和需求。 以下是几种常用技术及其特点&#xff1a; 游戏引擎技术 游戏引擎提供了强大的3D图形渲染和交互功能&…

区块链学习笔记3--以太坊

智能合约&#xff1a;跑在以太坊系统中的代码合同&#xff0c;其实质是一段代码。目前已经存在180多万个智能合约。 智能合约能表达&#xff1a;规则明确&#xff0c;不受主观因素影响的业务。 智能合约能表达&#xff1a;规则不轻易修改的业务 如果业务的规则经常变化&#x…

【C++】关键字、命名空间、输入和输出、缺省参数的深入了解

目录 一、C关键字二、命名空间2.1 为什么存在命名空间&#xff1f;2.2 命名空间定义2.3 命名空间使用 三、C输入&输出四、缺省函数4.1 缺省函数分类 总结 一、C关键字 C一共有63个关键字 其中红色圈出来的32个关键字同时也是C语言的 二、命名空间 2.1 为什么存在命名空间…

.net core8 使用JWT鉴权(附当前源码)

说明 该文章是属于OverallAuth2.0系列文章&#xff0c;每周更新一篇该系列文章&#xff08;从0到1完成系统开发&#xff09;。 该系统文章&#xff0c;我会尽量说的非常详细&#xff0c;做到不管新手、老手都能看懂。 说明&#xff1a;OverallAuth2.0 是一个简单、易懂、功能强…

【Vmware16安装教程】

&#x1f4d6;Vmware16安装教程 ✅1.下载✅2.安装 ✅1.下载 官网地址&#xff1a;https://www.vmware.com/ 百度云盘&#xff1a;Vmware16下载 123云盘&#xff1a;Vmware16下载 ✅2.安装 1.双击安装包VMware-workstation-full-16.1.0-LinuxProbe.Com.exe&#xff0c;点击…

requests-html的具体使用方法有哪些?

‌requests-html是一个功能强大的Python库&#xff0c;用于发送HTTP请求和解析HTML内容。它的使用方法包括安装库、基本使用、发送带有参数的请求、图片抓取实战案例、解析网页内容、执行JavaScript代码、使用CSS选择器来查找元素、继续跟踪链接并获取内容等。‌ ‌安装request…

Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)

题目&#xff1a;*18.29(某个目录下的文件数目) 编写一个程序&#xff0c;提示用户输入一个目录&#xff0c;然后显示该目录下的文件数。 和上一题(18.28)的思路差不多&#xff0c;把找到文件后累加大小到变量变成计数1即可。 Java语言程序设计基础篇_编程练习题*18.28 (非递…

Leetcode Hot 100刷题记录 -Day14(矩阵置0)

矩阵置0 问题描述&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2&#xff1a;…

STL模板库

一、模板 1、什么是模板 C语言中提供一种自动生成代码的技术&#xff0c;这种技术可以让程序员在编程时不需要考虑数据类型&#xff0c;而专注思考业务逻辑和算法&#xff0c;程序员只需要编写好代码的整体框架&#xff0c;具体的数据类型由使用者提供&#xff0c;这就叫模板…

JavaDS —— 图

图的概念 图是由顶点集合以及顶点之间的关系组成的一种数据结构&#xff1a;G &#xff08;V&#xff0c;E&#xff09; 其中 V 表示的是顶点集合 &#xff1a; V { x | x 属于某个数据对象集} 是有穷非空集合 E 叫做边的集合 &#xff1a; E {(x, y) | x, y 属于 V} 或者 …

Python基础语法(3)下

列表和元组 列表是什么&#xff0c;元组是什么 编程中&#xff0c;经常需要使用变量&#xff0c;来保存/表示数据。变量就是内存空间&#xff0c;用来表示或者存储数据。 如果代码中需要表示的数据个数比较少&#xff0c;我们直接创建多个变量即可。 num1 10 num2 20 num3…

【Git原理与使用】版本管理与分支管理(1)

目录 一、基本操作 1、初识Git 2、Git安装[Linux-centos] 3、Git安装[ Linnx-ubuntu] 4、创建git本地仓库 5、配置Git 6、认识工作区、暂存区、版本库 7、添加文件 8、查看历史提交记录 9、查看.git文件目录结构 10、查看版本库对象的内容 11、小结&#xff08;在本地的.git仓库…

javaMail

在Java程序中发送电子邮件通常依赖于JavaMail API。JavaMail API是Java的一部分&#xff0c;用于发送和接收电子邮件。以下是一个使用JavaMail API发送简单电子邮件的基本步骤和示例代码。 步骤 1: 添加JavaMail依赖 首先&#xff0c;确保你的项目中包含了JavaMail的依赖。如…

Comsol 多孔弹性波应用三:吸声器(超宽频带)

超宽频带吸声材料&#xff08;Ultra-wideband absorbing materials&#xff09;是指能够在非常宽的频率范围内吸收声波的材料。传统的吸声材料通常只能在较窄的频率范围内有效吸收声波&#xff0c;而超宽频带吸声材料可以在更广泛的频率范围内实现高效的吸声效果。这使得超宽频…

关于加强银行业保险业移动互联网应用程序管理的通知

近日,国家金融监督管理总局印发《关于加强银行业保险业移动互联网应用程序管理的通知》(下称“《通知》”),指导银行业金融机构、保险业金融机构和金融控股公司(以下统称金融机构)有序规范建设移动互联网应用程序(下称“移动应用”)。 《通知》指出,金融机构应当…