IBM Support

使用反射代理类加载器的潜在内存使用问题

Troubleshooting


Problem

大量的类加载器 sun/reflect/DelegatingClassLoader,用来加载sun/reflect/GeneratedMethodAccessor类,可能导致潜在的占用大量本机内存空间问题。

Symptom

应用服务器进程占用的内存会显著增大。您还有可能遇到抛出的内存溢出错误。

Cause

当使用Java反射时,Java虚拟机有两种方法获取被反射的类的信息。它可以使用一个JNI存取器。如果使用Java字节码存取器,则需要拥有它自己的Java类和类加载器(sun/reflect/GeneratedMethodAccessor类和sun/reflect/DelegatingClassLoader)。这些类和类加载器使用本机内存。字节码存取器也可以被JIT编译,这样会增加本机内存的使用。如果Java反射被频繁使用,会显著地增加本机内存的使用。

Java虚拟机会首先使用JNI存取器,然后在访问了同一个类若干次后,会改为使用Java字节码存取器。这种当Java虚拟机从JNI存取器改为字节码存取器的行为被称为膨胀。幸运的是,我们可以通过一个Java属性控制这种行为。属性sun.reflect.inflationThreshold会告诉Java虚拟机使用JNI存取器多少次。如果设为0,则总是使用JNI存取器。由于字节码存取器比JNI存取器使用更多本机内存,当我们看到大量Java反射时,最好使用JNI存取器。我们只需要设置inflationThreshold属性值为0即可。

Diagnosing The Problem

如果在javacore或heapdump中有大量sun/reflect/DelegatingClassLoader类加载器,您可能遇到了此问题。

Resolving The Problem

设置Java属性sun.reflect.inflationThreshold值为0。

1. 访问WebSphere应用程序服务器管理控制台
服务器 > 应用程序服务器 > 服务器名称
2. 在服务器基础结构部分,展开Java和进程管理,选择进程定义
3. 在其他属性部分选择Java虚拟机,在通用JVM参数输入框里添加以下字符串
-Dsun.reflect.inflationThreshold=0
4. 点击“确定”,保存至主配置。
需要重启应用程序服务器使设置生效。

Related Information

[{"Product":{"code":"SSEQTP","label":"WebSphere Application Server"},"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Component":"Out of Memory","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF010","label":"HP-UX"},{"code":"PF016","label":"Linux"},{"code":"PF027","label":"Solaris"},{"code":"PF033","label":"Windows"}],"Version":"8.0;7.0;6.1","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Document Information

Modified date:
03 December 2019

UID

swg21636746