提供一种低开销的Java堆分配采样方式,可通过JVMTI访问。
创新互联主营巴南网站建设的网络公司,主营网站建设方案,app软件开发公司,巴南h5微信平台小程序开发搭建,巴南网站营销推广欢迎巴南等地区企业咨询
提供一种从JVM获取Java对象堆分配信息的方法:
用户非常需要理解堆的内容。糟糕的堆管理可能会导致堆耗尽和GC抖动等问题。因此,人们开发了许多工具来允许用户自省他们的堆,例如Java Flight Recorder、jmap、YourKit和VisualVM工具。
大多数现有工具缺少的一个信息是特定分配的调用站点。堆转储和堆直方图不包含此信息。此信息对于调试内存问题非常重要,因为它告诉开发人员代码中发生特定(特别糟糕的)分配的确切位置。
目前有两种方法从热点获取这些信息:
该建议通过提供可扩展的JVMTI接口来缓解这些问题,该接口允许用户定义采样间隔并返回一组活动堆栈跟踪。
这里提出的面向用户的堆采样特性API由JVMTI的扩展组成,该扩展允许进行堆分析。以下系统依赖于提供回调的事件通知系统,例如:
void JNICALL
SampledObjectAlloc(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jobject object,
jclass object_klass,
jlong size)
说明:
新的API还包括一个新的JVMTI方法:
jvmtiError SetHeapSamplingInterval(jvmtiEnv* env, jint sampling_interval)
其中sampling_interval是两次采样之间分配的平均字节数。该方法的规格为:
注意,采样间隔是不精确的。每次出现一个样本时,在下一个样本被选择之前的字节数将是给定平均间隔的伪随机。这是为了避免抽样偏差;例如,如果相同的分配每512KB发生一次,512KB采样间隔将始终对相同的分配进行采样。因此,虽然采样间隔并不总是选择的间隔,但在大量的样本之后,它会趋向于它。
要启用此功能,用户将使用通常的事件通知调用来操作:
jvmti->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL)
该事件将在分配初始化并正确设置时发送,因此略晚于实际代码执行分配之后。缺省情况下,平均采样间隔为512KB。
启用采样事件系统的最低要求是使用JVMTI_ENABLE和事件类型
JVMTI_EVENT_SAMPLED_OBJECT_ALLOC调用SetEventNotificationMode。要修改采样间隔,用户调用SetHeapSamplingInterval方法。
禁用方式,
jvmti->SetEventNotificationMode(jvmti, JVMTI_DISABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL)
禁用事件通知并自动禁用采样器。
通过SetEventNotificationMode再次调用采样器将使用当前设置的采样间隔重新启用采样器(默认为512KB或用户通过SetHeapSamplingInterval传递的最后一个值)。
为了保护新特性并使其成为VM实现的可选特性,在jvmtiCapabilities中引入了名为
can_generate_sampled_object_alloc_events的新功能。
使用通知系统提供了一种仅为特定线程发送事件的直接方法。这是通过SetEventNotificationMode完成的,并提供第三个参数,其中包含要修改的线程。
下面的部分提供代码片段来演示采样器的API。首先,启用功能和事件通知:
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.SampledObjectAlloc = &SampledObjectAlloc;
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
caps.can_generate_sampled_object_alloc_events = 1;
if (JVMTI_ERROR_NONE != (*jvmti)->AddCapabilities(jvmti, &caps)) {
return JNI_ERR;
}
if (JVMTI_ERROR_NONE != (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL)) {
return JNI_ERR;
}
if (JVMTI_ERROR_NONE != (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)) {
return JNI_ERR;
}
// Set the sampler to 1MB.
if (JVMTI_ERROR_NONE != (*jvmti)->SetHeapSamplingInterval(jvmti, 1024 * 1024)) {
return JNI_ERR;
}
禁用采样器(禁用事件和采样器):
if (JVMTI_ERROR_NONE != (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE,
JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL)) {
return JNI_ERR;
}
要重新启用1024 * 1024字节采样间隔的采样器,需要一个简单的调用来启用事件:
if (JVMTI_ERROR_NONE != (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL)) {
return JNI_ERR;
}
当事件生成时,回调可以使用JVMTI GetStackTrace方法捕获堆栈跟踪。回调获得的jobject引用也可以包装成JNI弱引用,以帮助确定对象何时已被垃圾收集。这种方法允许用户收集关于采样对象的数据,以及仍然被认为是活动的对象的数据,这是了解作业行为的好方法。
例如,可以这样做:
extern "C" JNIEXPORT void JNICALL SampledObjectAlloc(jvmtiEnv *env,
JNIEnv* jni,
jthread thread,
jobject object,
jclass klass,
jlong size) {
jvmtiFrameInfo frames[32];
jint frame_count;
jvmtiError err;
err = global_jvmti->GetStackTrace(NULL, 0, 32, frames, &frame_count);
if (err == JVMTI_ERROR_NONE && frame_count >= 1) {
jweak ref = jni->NewWeakGlobalRef(object);
internal_storage.add(jni, ref, size, thread, frames, frame_count);
}
}
如果internal_storage是一个可以处理采样对象的数据结构,请考虑是否需要清理任何垃圾收集的样本,等等。该实现的内部是特定于使用的,超出了这个JEP的范围。
采样间隔可以用作减少分析开销的一种手段。使用512KB的采样间隔,开销应该足够低,用户可以合理地在默认情况下打开系统。
目前的原型和实现证明了该方法的可行性。它包括五个部分:
对于这个JEP中提出的系统,有多种替代方案。介绍中已经介绍了两个:Flight Recorder提供了一个有趣的替代方案。这个实现提供了几个优点。首先,JFR不允许设置抽样大小或提供回调。其次,当缓冲区耗尽时,JFR使用缓冲区系统可能导致分配丢失。最后,JFR事件系统没有提供跟踪已被垃圾收集的对象的方法,这意味着不可能使用它来提供有关活动对象和垃圾收集对象的信息。
另一种替代方法是使用ASM的字节码插装。它的开销让人望而却步,不是一个可行的解决方案。
这个JEP向JVMTI添加了一个新特性,JVMTI是用于各种开发和监视工具的重要API/框架。有了它,JVMTI代理可以使用低开销的堆分析API以及其他JVMTI功能,这为工具提供了极大的灵活性。例如,由代理决定是否需要在每个事件点收集堆栈跟踪。
JTreg框架中针对该特性有16个测试:使用多个线程打开/关闭,同时分配多个线程,测试数据是否以正确的间隔采样,以及收集的堆栈是否反映正确的程序信息。
禁用该特性不会造成性能损失或风险。没有启用系统的用户不会感知到性能差异。
但是,启用该特性会有潜在的性能/内存损失。在最初的原型实现中,开销是最小的(<2%)。这使用了一个更重量级的机制来修改JIT代码。在这里给出的最终版本中,系统依赖于TLAB代码,并且不应该经历这种回归。
目前对Dacapo基准测试的评估显示开销为:
标题名称:如何低开销的监控JVM对象分配及分配对象的线程
标题链接:http://www.36103.cn/qtweb/news31/4481.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联