从 Java 但不是从命令行执行时出现 NoSuchFieldError
NoSuchFieldError when executed from Java but not from command line
是否可以让java使用命令行环境而不是它自己的环境?
我有一个 java 程序使用
调用 bash 脚本
final ProcessBuilder pb = new ProcessBuilder("bash", "-x", exportScriptLoc, platformId, oldWorkFlowId,
newWorkFlowId).inheritIO();
pb.directory(new File("/opt/nis/ddziak-dev/nis-hadoop"));
final Process p = pb.start();
p.waitFor();
final int exitValue = p.exitValue();
p.destroy();
if (exitValue == 0) {
当我在命令行上执行脚本时,它的行为符合预期。当我的 java 程序执行脚本时,它会产生以下异常:
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.java:347)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:681)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:625)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.main(RunJar.java:212)
Caused by: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
at org.apache.hadoop.hive.metastore.MetaStoreUtils.newInstance(MetaStoreUtils.java:1422)
at org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.<init>(RetryingMetaStoreClient.java:62)
at org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.getProxy(RetryingMetaStoreClient.java:72)
at org.apache.hadoop.hive.ql.metadata.Hive.createMetaStoreClient(Hive.java:2457)
at org.apache.hadoop.hive.ql.metadata.Hive.getMSC(Hive.java:2469)
at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.java:341)
... 7 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.apache.hadoop.hive.metastore.MetaStoreUtils.newInstance(MetaStoreUtils.java:1420)
... 12 more
Caused by: java.lang.NoSuchFieldError: SASL_PROPS
at org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge20S.getHadoopSaslProperties(HadoopThriftAuthBridge20S.java:127)
at org.apache.hadoop.hive.metastore.MetaStoreUtils.getMetaStoreSaslProperties(MetaStoreUtils.java:1485)
at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.open(HiveMetaStoreClient.java:322)
at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.<init>(HiveMetaStoreClient.java:214)
... 17 more
脚本如下
#!/bin/bash
. ~/.bash_profile
export HIVE_HOME=/usr/lib/hive
#export PATH=$PATH:$HIVE_HOME/bin
env
echo "hive -S -e \"show partitions nis.subscribers
partition(destinationPlatformId='', build='');\"|awk '{if(NR>1)print}'" >> subscribers.out
PARTITIONS=`/usr/bin/hive -S -e "show partitions nis.subscribers
partition(destinationPlatformId='', build='');"|awk '{if(NR>1)print}'`
echo "${PARTITIONS}"
if [ -z "$PARTITIONS" ]
then
exit 2
fi
echo "${PARTITIONS}"
hqlOut=`/usr/bin/hive -S -hiveconf destPlatId= -hiveconf newWorkFlowId= -hiveconf oldWorkFlowId= -f /opt/nis/ddziak-dev/nis-
hadoop/dapLib/updateSubscriberHiveTable.hql`
newPARTITIONS=`/usr/bin/hive -S -e "show partitions nis.subscribers partition(destinationPlatformId='');"|awk '{if(NR>1)print}'`
if [ -z "$newPARTITIONS" ]
then
exit 3
fi
Is it possible to have java use the command line's environment instead of its own?
这取决于你所说的 "the command line's environment" 是什么意思。如果你的意思是狭义的从变量名到值的映射,那么
用于启动 VM 的 java
命令从启动它的命令获取其环境。这更有可能解决 "the command line's environment".
除非您采取行动产生不同的效果(并且提供的代码不会),否则您在 ProcessBuilder
的帮助下启动的进程将继承 VM 环境的副本。
但我认为您找错人了。虽然可以想象环境问题可能会间接导致 java.lang.NoSuchFieldError
,但这样的 Error
是
Thrown if an application tries to access or modify a specified field
of an object, and that object no longer has that field.
Normally, this error is caught by the compiler; this error can only
occur at run time if the definition of a class has incompatibly
changed.
(API docs)
这表明错误的最直接原因是您的运行时 class路径中的 classes 不匹配。 Field 在此上下文中表示 class 的成员变量,因此这就是 Java 正在寻找 SASL_PROPS
的内容(尽管我不清楚class 应该有那个字段。
是否可以让java使用命令行环境而不是它自己的环境?
我有一个 java 程序使用
调用 bash 脚本final ProcessBuilder pb = new ProcessBuilder("bash", "-x", exportScriptLoc, platformId, oldWorkFlowId,
newWorkFlowId).inheritIO();
pb.directory(new File("/opt/nis/ddziak-dev/nis-hadoop"));
final Process p = pb.start();
p.waitFor();
final int exitValue = p.exitValue();
p.destroy();
if (exitValue == 0) {
当我在命令行上执行脚本时,它的行为符合预期。当我的 java 程序执行脚本时,它会产生以下异常:
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.java:347)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:681)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:625)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.main(RunJar.java:212)
Caused by: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
at org.apache.hadoop.hive.metastore.MetaStoreUtils.newInstance(MetaStoreUtils.java:1422)
at org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.<init>(RetryingMetaStoreClient.java:62)
at org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.getProxy(RetryingMetaStoreClient.java:72)
at org.apache.hadoop.hive.ql.metadata.Hive.createMetaStoreClient(Hive.java:2457)
at org.apache.hadoop.hive.ql.metadata.Hive.getMSC(Hive.java:2469)
at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.java:341)
... 7 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.apache.hadoop.hive.metastore.MetaStoreUtils.newInstance(MetaStoreUtils.java:1420)
... 12 more
Caused by: java.lang.NoSuchFieldError: SASL_PROPS
at org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge20S.getHadoopSaslProperties(HadoopThriftAuthBridge20S.java:127)
at org.apache.hadoop.hive.metastore.MetaStoreUtils.getMetaStoreSaslProperties(MetaStoreUtils.java:1485)
at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.open(HiveMetaStoreClient.java:322)
at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.<init>(HiveMetaStoreClient.java:214)
... 17 more
脚本如下
#!/bin/bash
. ~/.bash_profile
export HIVE_HOME=/usr/lib/hive
#export PATH=$PATH:$HIVE_HOME/bin
env
echo "hive -S -e \"show partitions nis.subscribers
partition(destinationPlatformId='', build='');\"|awk '{if(NR>1)print}'" >> subscribers.out
PARTITIONS=`/usr/bin/hive -S -e "show partitions nis.subscribers
partition(destinationPlatformId='', build='');"|awk '{if(NR>1)print}'`
echo "${PARTITIONS}"
if [ -z "$PARTITIONS" ]
then
exit 2
fi
echo "${PARTITIONS}"
hqlOut=`/usr/bin/hive -S -hiveconf destPlatId= -hiveconf newWorkFlowId= -hiveconf oldWorkFlowId= -f /opt/nis/ddziak-dev/nis-
hadoop/dapLib/updateSubscriberHiveTable.hql`
newPARTITIONS=`/usr/bin/hive -S -e "show partitions nis.subscribers partition(destinationPlatformId='');"|awk '{if(NR>1)print}'`
if [ -z "$newPARTITIONS" ]
then
exit 3
fi
Is it possible to have java use the command line's environment instead of its own?
这取决于你所说的 "the command line's environment" 是什么意思。如果你的意思是狭义的从变量名到值的映射,那么
用于启动 VM 的
java
命令从启动它的命令获取其环境。这更有可能解决 "the command line's environment".除非您采取行动产生不同的效果(并且提供的代码不会),否则您在
ProcessBuilder
的帮助下启动的进程将继承 VM 环境的副本。
但我认为您找错人了。虽然可以想象环境问题可能会间接导致 java.lang.NoSuchFieldError
,但这样的 Error
是
Thrown if an application tries to access or modify a specified field of an object, and that object no longer has that field.
Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.
(API docs)
这表明错误的最直接原因是您的运行时 class路径中的 classes 不匹配。 Field 在此上下文中表示 class 的成员变量,因此这就是 Java 正在寻找 SASL_PROPS
的内容(尽管我不清楚class 应该有那个字段。