问题:
c++通过JNI调用hive-jdbc连接hive-server,当hadoop版本为2.6时,总是报错

Illegal Hadoop Version: Unknown (expected A.B.* format)
原因:
hadoop 2.6 获取版本源码如下(hadoop 3.x 版本修改了此代码,所以不会遇到此问题):
protected VersionInfo(String component) {
info = new Properties();
String versionInfoFile = component + "-version-info.properties";
InputStream is = null;
try {
is = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(versionInfoFile);
if (is == null) {
throw new IOException("Resource not found");
}
info.load(is);
} catch (IOException ex) {
LogFactory.getLog(getClass()).warn("Could not read ‘" +
versionInfoFile + "‘, " + ex.toString(), ex);
} finally {
IOUtils.closeStream(is);
}
}
调用了函数 getContextClassLoader 获取classloader来加载hadoop版本信息文件,这个函数默认获取到的是system class loader,但是在JNI中使用了函数AttachCurrentThread,函数getContextClassLoader 获取到的将是 bootstrap class loader,加载文件错误,所以会抛出获取hadoop版本异常
Java Native Interface Specification: 5 - The Invocation API (oracle.com)
AttachCurrentThread
jint AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args);Attaches the current thread to a Java VM. Returns a JNI interface pointer in the
JNIEnvargument.Trying to attach a thread that is already attached is a no-op.
A native thread cannot be attached simultaneously to two Java VMs.
When a thread is attached to the VM, the context class loader is the bootstrap loader.
解决方法:
连接hive之前先调用函数 setContextClassLoader 重新设置 context loader
java.lang.Thread.currentThread().setContextClassLoader(
java.lang.ClassLoader.getSystemClassLoader()
);
原文:https://www.cnblogs.com/kouruyi/p/14871276.html