Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
jni-util.h
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 
16 #ifndef IMPALA_UTIL_JNI_UTIL_H
17 #define IMPALA_UTIL_JNI_UTIL_H
18 
19 #include <jni.h>
20 #include <string>
21 #include <vector>
22 
23 #include "common/status.h"
24 #include "gen-cpp/Frontend_types.h"
25 
26 #define THROW_IF_ERROR_WITH_LOGGING(stmt, env, adaptor) \
27  do { \
28  Status status = (stmt); \
29  if (!status.ok()) { \
30  (adaptor)->WriteErrorLog(); \
31  (adaptor)->WriteFileErrors(); \
32  (env)->ThrowNew((adaptor)->impala_exc_cl(), status.GetDetail().c_str()); \
33  return; \
34  } \
35  } while (false)
36 
37 #define THROW_IF_ERROR(stmt, env, impala_exc_cl) \
38  do { \
39  Status status = (stmt); \
40  if (!status.ok()) { \
41  (env)->ThrowNew((impala_exc_cl), status.GetDetail().c_str()); \
42  return; \
43  } \
44  } while (false)
45 
46 #define THROW_IF_ERROR_RET(stmt, env, impala_exc_cl, ret) \
47  do { \
48  Status status = (stmt); \
49  if (!status.ok()) { \
50  (env)->ThrowNew((impala_exc_cl), status.GetDetail().c_str()); \
51  return (ret); \
52  } \
53  } while (false)
54 
55 #define THROW_IF_EXC(env, exc_class) \
56  do { \
57  jthrowable exc = (env)->ExceptionOccurred(); \
58  if (exc != NULL) { \
59  DCHECK((throwable_to_string_id_) != NULL); \
60  jstring stack = (jstring) env->CallStaticObjectMethod(JniUtil::jni_util_class(), \
61  (JniUtil::throwable_to_stack_trace_id()), exc); \
62  jboolean is_copy; \
63  const char* c_stack = \
64  reinterpret_cast<const char*>((env)->GetStringUTFChars(stack, &is_copy)); \
65  (env)->ExceptionClear(); \
66  (env)->ThrowNew((exc_class), c_stack); \
67  return; \
68  } \
69  } while (false)
70 
71 #define RETURN_IF_EXC(env) \
72  do { \
73  jthrowable exc = (env)->ExceptionOccurred(); \
74  if (exc != NULL) { \
75  jstring stack = (jstring) env->CallStaticObjectMethod(JniUtil::jni_util_class(), \
76  (JniUtil::throwable_to_stack_trace_id()), exc); \
77  jboolean is_copy; \
78  const char* c_stack = \
79  reinterpret_cast<const char*>((env)->GetStringUTFChars(stack, &is_copy)); \
80  VLOG(1) << string(c_stack); \
81  return; \
82  } \
83  } while (false)
84 
85 #define EXIT_IF_EXC(env) \
86  do { \
87  jthrowable exc = (env)->ExceptionOccurred(); \
88  if (exc != NULL) { \
89  jstring stack = (jstring) env->CallStaticObjectMethod(JniUtil::jni_util_class(), \
90  (JniUtil::throwable_to_stack_trace_id()), exc); \
91  jboolean is_copy; \
92  const char* c_stack = \
93  reinterpret_cast<const char*>((env)->GetStringUTFChars(stack, &is_copy)); \
94  LOG(ERROR) << string(c_stack); \
95  exit(1); \
96  } \
97  } while (false)
98 
99 #define RETURN_ERROR_IF_EXC(env) \
100  do { \
101  jthrowable exc = (env)->ExceptionOccurred(); \
102  if (exc != NULL) return JniUtil::GetJniExceptionMsg(env);\
103  } while (false)
104 
105 #define EXIT_IF_JNIERROR(stmt) \
106  do { \
107  if ((stmt) != JNI_OK) { \
108  cerr << #stmt << " resulted in a jni error"; \
109  exit(1); \
110  } \
111  } while (false)
112 
113 #define RETURN_IF_JNIERROR(stmt) \
114  do { \
115  if ((stmt) != JNI_OK) { \
116  stringstream out; \
117  out << #stmt << " resulted in a jni error"; \
118  return Status(out.str()); \
119  } \
120  } while (false)
121 
123 extern "C" { extern JNIEnv* getJNIEnv(void); }
124 
125 namespace impala {
126 
127 class Status;
128 
134  public:
135  JniLocalFrame(): env_(NULL) {}
136  ~JniLocalFrame() { if (env_ != NULL) env_->PopLocalFrame(NULL); }
137 
142  Status push(JNIEnv* env, int max_local_ref=10);
143 
144  private:
145  JNIEnv* env_;
146 };
147 
151  const std::string name;
152 
154  const std::string signature;
155 
157  jmethodID* method_id;
158 };
159 
174 class JniUtil {
175  public:
177  static void InitLibhdfs();
178 
180  static Status Init();
181 
185  static bool ClassExists(JNIEnv* env, const char* class_str);
186 
191  static Status GetGlobalClassRef(JNIEnv* env, const char* class_str, jclass* class_ref);
192 
197  static Status LocalToGlobalRef(JNIEnv* env, jobject local_ref, jobject* global_ref);
198 
199  static jmethodID throwable_to_string_id() { return throwable_to_string_id_; }
201 
203  static jclass jni_util_class() { return jni_util_cl_; }
204 
206  static jclass internal_exc_class() { return internal_exc_cl_; }
207 
209  static Status Cleanup();
210 
214  static Status GetJniExceptionMsg(JNIEnv* env, bool log_stack = true,
215  const std::string& prefix = "");
216 
219  static Status GetJvmMetrics(const TGetJvmMetricsRequest& request,
220  TGetJvmMetricsResponse* result);
221 
225  static Status LoadJniMethod(JNIEnv* jni_env, const jclass& jni_class,
226  JniMethodDescriptor* descriptor);
227 
230  template <typename T>
231  static Status CallJniMethod(const jobject& obj, const jmethodID& method, const T& arg) {
232  JNIEnv* jni_env = getJNIEnv();
233  jbyteArray request_bytes;
234  JniLocalFrame jni_frame;
235  RETURN_IF_ERROR(jni_frame.push(jni_env));
236  RETURN_IF_ERROR(SerializeThriftMsg(jni_env, &arg, &request_bytes));
237  jni_env->CallObjectMethod(obj, method, request_bytes);
238  RETURN_ERROR_IF_EXC(jni_env);
239  return Status::OK;
240  }
241 
242  template <typename R>
243  static Status CallJniMethod(const jobject& obj, const jmethodID& method, R* response) {
244  JNIEnv* jni_env = getJNIEnv();
245  JniLocalFrame jni_frame;
246  RETURN_IF_ERROR(jni_frame.push(jni_env));
247  jbyteArray result_bytes = static_cast<jbyteArray>(
248  jni_env->CallObjectMethod(obj, method));
249  RETURN_ERROR_IF_EXC(jni_env);
250  RETURN_IF_ERROR(DeserializeThriftMsg(jni_env, result_bytes, response));
251  return Status::OK;
252  }
253 
254  template <typename T, typename R>
255  static Status CallJniMethod(const jobject& obj, const jmethodID& method,
256  const T& arg, R* response) {
257  JNIEnv* jni_env = getJNIEnv();
258  jbyteArray request_bytes;
259  JniLocalFrame jni_frame;
260  RETURN_IF_ERROR(jni_frame.push(jni_env));
261  RETURN_IF_ERROR(SerializeThriftMsg(jni_env, &arg, &request_bytes));
262  jbyteArray result_bytes = static_cast<jbyteArray>(
263  jni_env->CallObjectMethod(obj, method, request_bytes));
264  RETURN_ERROR_IF_EXC(jni_env);
265  RETURN_IF_ERROR(DeserializeThriftMsg(jni_env, result_bytes, response));
266  return Status::OK;
267  }
268 
269  template <typename T>
270  static Status CallJniMethod(const jobject& obj, const jmethodID& method,
271  const T& arg, std::string* response) {
272  JNIEnv* jni_env = getJNIEnv();
273  jbyteArray request_bytes;
274  JniLocalFrame jni_frame;
275  RETURN_IF_ERROR(jni_frame.push(jni_env));
276  RETURN_IF_ERROR(SerializeThriftMsg(jni_env, &arg, &request_bytes));
277  jstring java_response_string = static_cast<jstring>(
278  jni_env->CallObjectMethod(obj, method, request_bytes));
279  RETURN_ERROR_IF_EXC(jni_env);
280  jboolean is_copy;
281  const char *str = jni_env->GetStringUTFChars(java_response_string, &is_copy);
282  RETURN_ERROR_IF_EXC(jni_env);
283  *response = str;
284  jni_env->ReleaseStringUTFChars(java_response_string, str);
285  RETURN_ERROR_IF_EXC(jni_env);
286  return Status::OK;
287  }
288 
289  private:
290  static jclass jni_util_cl_;
291  static jclass internal_exc_cl_;
292  static jmethodID throwable_to_string_id_;
294  static jmethodID get_jvm_metrics_id_;
297  static std::vector<jobject> global_refs_;
298 };
299 
300 }
301 
302 #endif
static jclass jni_util_cl_
Definition: jni-util.h:290
static std::vector< jobject > global_refs_
Definition: jni-util.h:297
const std::string signature
JNI-style method signature.
Definition: jni-util.h:154
#define RETURN_IF_ERROR(stmt)
some generally useful macros
Definition: status.h:242
static Status LoadJniMethod(JNIEnv *jni_env, const jclass &jni_class, JniMethodDescriptor *descriptor)
Definition: jni-util.cc:193
static jclass internal_exc_class()
Global reference to InternalException class.
Definition: jni-util.h:206
static jmethodID throwable_to_stack_trace_id()
Definition: jni-util.h:200
static Status Init()
Find JniUtil class, and get JniUtil.throwableToString method id.
Definition: jni-util.cc:74
static Status CallJniMethod(const jobject &obj, const jmethodID &method, R *response)
Definition: jni-util.h:243
static Status Cleanup()
Delete all global references: class members, and those stored in global_refs_.
Definition: jni-util.cc:147
static jmethodID throwable_to_stack_trace_id_
Definition: jni-util.h:293
static Status LocalToGlobalRef(JNIEnv *env, jobject local_ref, jobject *global_ref)
Definition: jni-util.cc:67
static void InitLibhdfs()
Call this prior to any libhdfs calls.
Definition: jni-util.cc:140
static Status CallJniMethod(const jobject &obj, const jmethodID &method, const T &arg, std::string *response)
Definition: jni-util.h:270
static jmethodID get_jvm_metrics_id_
Definition: jni-util.h:294
static Status GetJniExceptionMsg(JNIEnv *env, bool log_stack=true, const std::string &prefix="")
Definition: jni-util.cc:161
Status push(JNIEnv *env, int max_local_ref=10)
Definition: jni-util.cc:34
Describes one method to look up in a Java object.
Definition: jni-util.h:149
static Status CallJniMethod(const jobject &obj, const jmethodID &method, const T &arg, R *response)
Definition: jni-util.h:255
const std::string name
Name of the method, case must match.
Definition: jni-util.h:151
#define RETURN_ERROR_IF_EXC(env)
Definition: jni-util.h:99
static jclass jni_util_class()
Global reference to java JniUtil class.
Definition: jni-util.h:203
static const Status OK
Definition: status.h:87
static bool ClassExists(JNIEnv *env, const char *class_str)
Definition: jni-util.cc:45
jmethodID * method_id
Handle to the method.
Definition: jni-util.h:157
static Status GetGlobalClassRef(JNIEnv *env, const char *class_str, jclass *class_ref)
Definition: jni-util.cc:56
static jclass internal_exc_cl_
Definition: jni-util.h:291
static jmethodID throwable_to_string_id()
Definition: jni-util.h:199
Status DeserializeThriftMsg(JNIEnv *env, jbyteArray serialized_msg, T *deserialized_msg)
static Status GetJvmMetrics(const TGetJvmMetricsRequest &request, TGetJvmMetricsResponse *result)
Definition: jni-util.cc:188
static Status CallJniMethod(const jobject &obj, const jmethodID &method, const T &arg)
Definition: jni-util.h:231
Status SerializeThriftMsg(JNIEnv *env, T *msg, jbyteArray *serialized_msg)
static jmethodID throwable_to_string_id_
Definition: jni-util.h:292
JNIEnv * getJNIEnv(void)
C linkage for helper functions in hdfsJniHelper.h.