java - 从 Java 执行但不是从命令行执行时出现 NoSuchFieldError

标签 java bash hive environment-variables processbuilder

是否可以让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='$1', build='$2');\"|awk '{if(NR>1)print}'" >> subscribers.out
PARTITIONS=`/usr/bin/hive -S -e "show partitions nis.subscribers 
partition(destinationPlatformId='$1', build='$2');"|awk '{if(NR>1)print}'`
echo "${PARTITIONS}"
if [ -z "$PARTITIONS" ]
then
  exit 2
fi


echo "${PARTITIONS}"

hqlOut=`/usr/bin/hive -S -hiveconf destPlatId=$1 -hiveconf newWorkFlowId=$3 -hiveconf oldWorkFlowId=$2 -f /opt/nis/ddziak-dev/nis-
hadoop/dapLib/updateSubscriberHiveTable.hql`

newPARTITIONS=`/usr/bin/hive -S -e "show partitions nis.subscribers partition(destinationPlatformId='$1');"|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?

这取决于您所说的“命令行环境”的含义。如果您的意思是狭义上从变量名称到值的映射,那么

  • java启动 VM 的命令从启动它的命令获取其环境。这很可能适用于“命令行环境”。

  • 除非您采取行动产生不同的效果(并且所提供的代码不会),否则您在 ProcessBuilder 的帮助下启动进程将继承虚拟机环境的副本。

但我认为你找错了对象。尽管可以想象,环境问题可能会间接导致 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 )

这表明错误的最直接原因是运行时类路径中的类不匹配。 Field在此上下文中表示类的成员变量,因此这就是Java正在寻找的SASL_PROPS是(尽管我不清楚哪个类应该拥有该字段)。

关于java - 从 Java 执行但不是从命令行执行时出现 NoSuchFieldError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47639722/

相关文章:

Java线程查找系统时间

java等待光标显示问题

java - Eclipse:提取方法功能失败

linux - sh 返回 : can only `return' from a function or sourced script

types - 我可以在 hive 中将表从内部更改为外部吗?

java - 递归调用期间发生 StackOverflowError

linux - 如何比较两个文本文件,同时忽略从一个实例到下一个实例的更改字段?

python - 如何告诉 `complete` 回退到默认值?

hadoop - 在hdfs中找不到仓库

hadoop - 在Hive中使用Rlike查找正则表达式模式