由于之前为了不改hive的代码,用了反射的方式动态修改,导致了另一个问题出现。
我用的反射代码如下:(代码是针对local metastore写的), 主要是为了调用ObjectStore的shutdown()方法。
Hive hive = Hive.get();
Method method = Hive.class.getDeclaredMethod("getMSC");
method.setAccessible(true);
HiveMetaStoreClient msc = (HiveMetaStoreClient)method.invoke(hive);
Field field = HiveMetaStoreClient.class.getDeclaredField("client");
field.setAccessible(true);
HiveMetaStore.HMSHandler client = (HiveMetaStore.HMSHandler)field.get(msc);
if (client != null) {
method = HiveMetaStore.HMSHandler.class.getDeclaredMethod("getMS", boolean.class);
method.setAccessible(true);
ObjectStore os = (ObjectStore)method.invoke(client, false);
os.shutdown();
}
method = null;
field = null;
Hive.closeCurrent();
使用反射后,用jprofiler检查发现多了很多这些类
sun.reflect.DelegatingClassLoader
sun.reflect.GeneratedConstructorAccessor77
估计是反射引起的,类越來越多(还没有严谨的测试过,因为perm内存增长很缓慢)
看了几篇文章,没搞懂。。到StackOverflow去问
使用这个参数,通过jni的方式调用反射
-Dsun.reflect.inflationThreshold=0
我理解是使用反射会有两种途径,jni和Java bytecode,(It can use a JNI accessor, or a Java bytecode accessor),使用jni调用会慢一些,但使用Java bytecode会生成一个类和classloader (sun/reflect/GeneratedMethodAccessor
参考
StackOverflow
Potential native memory use in reflection delegating classloaders