src/jdk.packager/share/native/library/common/Java.cpp
branchJDK-8200758-branch
changeset 56982 e094d5483bd6
parent 56963 eaca4369b068
child 56983 01decb67d4f0
equal deleted inserted replaced
56963:eaca4369b068 56982:e094d5483bd6
     1 /*
       
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include "Java.h"
       
    27 #include "PlatformString.h"
       
    28 
       
    29 #include <list>
       
    30 
       
    31 
       
    32 //--------------------------------------------------------------------------------------------------
       
    33 
       
    34 #ifdef DEBUG
       
    35 TString JavaException::CreateExceptionMessage(JNIEnv* Env, jthrowable Exception,
       
    36     jmethodID GetCauseMethod, jmethodID GetStackTraceMethod, jmethodID ThrowableToTStringMethod,
       
    37     jmethodID FrameToTStringMethod) {
       
    38 
       
    39     TString result;
       
    40     jobjectArray frames = (jobjectArray)Env->CallObjectMethod(Exception, GetStackTraceMethod);
       
    41 
       
    42     // Append Throwable.toTString().
       
    43     if (0 != frames) {
       
    44         jstring jstr = (jstring)Env->CallObjectMethod(Exception, ThrowableToTStringMethod);
       
    45         const char* str = Env->GetStringUTFChars(jstr, 0);
       
    46         result += PlatformString(str).toPlatformString();
       
    47         Env->ReleaseStringUTFChars(jstr, str);
       
    48         Env->DeleteLocalRef(jstr);
       
    49     }
       
    50 
       
    51     // Append stack trace if one exists.
       
    52     if (Env->GetArrayLength(frames) > 0) {
       
    53         jsize i = 0;
       
    54 
       
    55         for (i = 0; i < Env->GetArrayLength(frames); i++) {
       
    56             // Get the string from the next frame and append it to
       
    57             // the error message.
       
    58             jobject frame = Env->GetObjectArrayElement(frames, i);
       
    59             jstring obj = (jstring)Env->CallObjectMethod(frame, FrameToTStringMethod);
       
    60             const char* str = Env->GetStringUTFChars(obj, 0);
       
    61             result += _T("\n  ");
       
    62             result += PlatformString(str).toPlatformString();
       
    63             Env->ReleaseStringUTFChars(obj, str);
       
    64             Env->DeleteLocalRef(obj);
       
    65             Env->DeleteLocalRef(frame);
       
    66         }
       
    67     }
       
    68 
       
    69     // If Exception has a cause then append the stack trace messages.
       
    70     if (0 != frames) {
       
    71         jthrowable cause = (jthrowable)Env->CallObjectMethod(Exception, GetCauseMethod);
       
    72 
       
    73         if (cause != NULL) {
       
    74             result += CreateExceptionMessage(Env, cause, GetCauseMethod,
       
    75                 GetStackTraceMethod, ThrowableToTStringMethod,
       
    76                 FrameToTStringMethod);
       
    77         }
       
    78     }
       
    79 
       
    80     return result;
       
    81 }
       
    82 #endif //DEBUG
       
    83 
       
    84 JavaException::JavaException() : Exception() {}
       
    85 
       
    86 //#ifdef WINDOWS
       
    87 JavaException::JavaException(JNIEnv *Env, const TString Message) : Exception(Message) {
       
    88 //#endif //WINDOWS
       
    89 //#ifdef POSIX
       
    90 //JavaException::JavaException(JNIEnv *Env, TString message) {
       
    91 //#endif //POSIX
       
    92 
       
    93     FEnv = Env;
       
    94     FException = Env->ExceptionOccurred();
       
    95     Env->ExceptionClear();
       
    96 
       
    97 #ifdef DEBUG
       
    98     Platform& platform = Platform::GetInstance();
       
    99 
       
   100     if (platform.GetDebugState() == dsNone) {
       
   101         jclass ThrowableClass = Env->FindClass("java/lang/Throwable");
       
   102 
       
   103         if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   104             Env->ExceptionClear();
       
   105             return;
       
   106         }
       
   107 
       
   108         jmethodID GetCauseMethod = Env->GetMethodID(ThrowableClass,
       
   109                                                     "getCause",
       
   110                                                     "()Ljava/lang/Throwable;");
       
   111 
       
   112         if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   113             Env->ExceptionClear();
       
   114             return;
       
   115         }
       
   116 
       
   117         jmethodID GetStackTraceMethod = Env->GetMethodID(ThrowableClass,
       
   118                                                             "getStackTrace",
       
   119                                                             "()[Ljava/lang/StackTraceElement;");
       
   120 
       
   121         if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   122             Env->ExceptionClear();
       
   123             return;
       
   124         }
       
   125 
       
   126         jmethodID ThrowableToTStringMethod = Env->GetMethodID(ThrowableClass,
       
   127                                                                 "toString",
       
   128                                                                 "()Ljava/lang/String;");
       
   129 
       
   130         if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   131             Env->ExceptionClear();
       
   132             return;
       
   133         }
       
   134 
       
   135         jclass FrameClass = Env->FindClass("java/lang/StackTraceElement");
       
   136 
       
   137         if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   138             Env->ExceptionClear();
       
   139             return;
       
   140         }
       
   141 
       
   142         jmethodID FrameToTStringMethod = Env->GetMethodID(FrameClass,
       
   143                                                             "toString",
       
   144                                                             "()Ljava/lang/String;");
       
   145 
       
   146         if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   147             Env->ExceptionClear();
       
   148             return;
       
   149         }
       
   150 
       
   151         TString lmessage = CreateExceptionMessage(Env, FException, GetCauseMethod,
       
   152             GetStackTraceMethod, ThrowableToTStringMethod, FrameToTStringMethod);
       
   153         SetMessage(lmessage);
       
   154     }
       
   155 #endif //DEBUG
       
   156 }
       
   157 
       
   158 void JavaException::Rethrow() {
       
   159     FEnv->Throw(FException);
       
   160 }
       
   161 
       
   162 //--------------------------------------------------------------------------------------------------
       
   163 
       
   164 JavaStaticMethod::JavaStaticMethod(JNIEnv *Env, jclass Class, jmethodID Method) {
       
   165     FEnv = Env;
       
   166     FClass = Class;
       
   167     FMethod = Method;
       
   168 }
       
   169 
       
   170 void JavaStaticMethod::CallVoidMethod(int Count, ...) {
       
   171     va_list args;
       
   172     va_start(args, Count);
       
   173     FEnv->CallStaticVoidMethodV(FClass, FMethod, args);
       
   174     va_end(args);
       
   175 
       
   176     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   177         Messages& messages = Messages::GetInstance();
       
   178         throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD));
       
   179     }
       
   180 }
       
   181 
       
   182 JavaStaticMethod::operator jmethodID () {
       
   183     return FMethod;
       
   184 }
       
   185 
       
   186 //--------------------------------------------------------------------------------------------------
       
   187 
       
   188 JavaMethod::JavaMethod(JNIEnv *Env, jobject Obj, jmethodID Method) {
       
   189     FEnv = Env;
       
   190     FObj = Obj;
       
   191     FMethod = Method;
       
   192 }
       
   193 
       
   194 void JavaMethod::CallVoidMethod(int Count, ...) {
       
   195     va_list args;
       
   196     va_start(args, Count);
       
   197     FEnv->CallVoidMethodV(FObj, FMethod, args);
       
   198     va_end(args);
       
   199 
       
   200     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   201         Messages& messages = Messages::GetInstance();
       
   202         throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD));
       
   203     }
       
   204 }
       
   205 
       
   206 JavaMethod::operator jmethodID () {
       
   207     return FMethod;
       
   208 }
       
   209 
       
   210 //--------------------------------------------------------------------------------------------------
       
   211 
       
   212 JavaClass::JavaClass(JNIEnv *Env, TString Name) {
       
   213     FEnv = Env;
       
   214     FClassName = Name;
       
   215     FClass = FEnv->FindClass(PlatformString(FClassName));
       
   216 
       
   217     if (FClass == NULL || FEnv->ExceptionCheck() == JNI_TRUE) {
       
   218         Messages& messages = Messages::GetInstance();
       
   219         TString message = messages.GetMessage(CLASS_NOT_FOUND);
       
   220         message = PlatformString::Format(message, FClassName.data());
       
   221         throw JavaException(FEnv, message);
       
   222     }
       
   223 }
       
   224 
       
   225 JavaClass::~JavaClass() {
       
   226     FEnv->DeleteLocalRef(FClass);
       
   227 
       
   228     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   229         // throw JavaException(FEnv, _T("Error"));  // VS2017 - FIXME
       
   230     }
       
   231 }
       
   232 
       
   233 JavaStaticMethod JavaClass::GetStaticMethod(TString Name, TString Signature) {
       
   234     jmethodID method = FEnv->GetStaticMethodID(FClass, PlatformString(Name), PlatformString(Signature));
       
   235 
       
   236     if (method == NULL || FEnv->ExceptionCheck() == JNI_TRUE) {
       
   237         Messages& messages = Messages::GetInstance();
       
   238         TString message = messages.GetMessage(METHOD_NOT_FOUND);
       
   239         message = PlatformString::Format(message, Name.data(), FClassName.data());
       
   240         throw JavaException(FEnv, message);
       
   241     }
       
   242 
       
   243     return JavaStaticMethod(FEnv, FClass, method);
       
   244 }
       
   245 
       
   246 JavaClass::operator jclass () {
       
   247     return FClass;
       
   248 }
       
   249 
       
   250 //--------------------------------------------------------------------------------------------------
       
   251 
       
   252 void JavaStringArray::Initialize(size_t Size) {
       
   253     JavaClass jstringClass(FEnv, _T("java/lang/String"));
       
   254 
       
   255     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   256         Messages& messages = Messages::GetInstance();
       
   257         TString message = messages.GetMessage(CLASS_NOT_FOUND);
       
   258         message = PlatformString::Format(message, _T("String"));
       
   259         throw JavaException(FEnv, message.data());
       
   260     }
       
   261 
       
   262     jstring str = PlatformString("").toJString(FEnv);
       
   263     FData = (jobjectArray)FEnv->NewObjectArray((jsize)Size, jstringClass, str);
       
   264 
       
   265     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   266         throw JavaException(FEnv, _T("Error"));
       
   267     }
       
   268 }
       
   269 
       
   270 JavaStringArray::JavaStringArray(JNIEnv *Env, size_t Size) {
       
   271     FEnv = Env;
       
   272     Initialize(Size);
       
   273 }
       
   274 
       
   275 JavaStringArray::JavaStringArray(JNIEnv *Env, jobjectArray Data) {
       
   276     FEnv = Env;
       
   277     FData = Data;
       
   278 }
       
   279 
       
   280 JavaStringArray::JavaStringArray(JNIEnv *Env, std::list<TString> Items) {
       
   281     FEnv = Env;
       
   282     Initialize(Items.size());
       
   283     unsigned int index = 0;
       
   284 
       
   285     for (std::list<TString>::const_iterator iterator = Items.begin(); iterator != Items.end(); iterator++) {
       
   286         TString item = *iterator;
       
   287         SetValue(index, PlatformString(item).toJString(FEnv));
       
   288         index++;
       
   289     }
       
   290 }
       
   291 
       
   292 jobjectArray JavaStringArray::GetData() {
       
   293     return FData;
       
   294 }
       
   295 
       
   296 void JavaStringArray::SetValue(jsize Index, jstring Item) {
       
   297     FEnv->SetObjectArrayElement(FData, Index, Item);
       
   298 
       
   299     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   300         throw JavaException(FEnv, _T("Error"));
       
   301     }
       
   302 }
       
   303 
       
   304 jstring JavaStringArray::GetValue(jsize Index) {
       
   305     jstring result = (jstring)FEnv->GetObjectArrayElement(FData, Index);
       
   306 
       
   307     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   308         throw JavaException(FEnv, _T("Error"));
       
   309     }
       
   310 
       
   311     return result;
       
   312 }
       
   313 
       
   314 unsigned int JavaStringArray::Count() {
       
   315     unsigned int result = FEnv->GetArrayLength(FData);
       
   316 
       
   317     if (FEnv->ExceptionCheck() == JNI_TRUE) {
       
   318         throw JavaException(FEnv, _T("Error"));
       
   319     }
       
   320 
       
   321     return result;
       
   322 }
       
   323 
       
   324 //--------------------------------------------------------------------------------------------------