Home | History | Annotate | Download | only in openjdkjvmti
      1 /* Copyright (C) 2017 The Android Open Source Project
      2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      3  *
      4  * This file implements interfaces from the file jvmti.h. This implementation
      5  * is licensed under the same terms as the file jvmti.h.  The
      6  * copyright and license information for the file jvmti.h follows.
      7  *
      8  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
      9  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     10  *
     11  * This code is free software; you can redistribute it and/or modify it
     12  * under the terms of the GNU General Public License version 2 only, as
     13  * published by the Free Software Foundation.  Oracle designates this
     14  * particular file as subject to the "Classpath" exception as provided
     15  * by Oracle in the LICENSE file that accompanied this code.
     16  *
     17  * This code is distributed in the hope that it will be useful, but WITHOUT
     18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     20  * version 2 for more details (a copy is included in the LICENSE file that
     21  * accompanied this code).
     22  *
     23  * You should have received a copy of the GNU General Public License version
     24  * 2 along with this work; if not, write to the Free Software Foundation,
     25  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     26  *
     27  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     28  * or visit www.oracle.com if you need additional information or have any
     29  * questions.
     30  */
     31 
     32 #include "ti_properties.h"
     33 
     34 #include <string.h>
     35 #include <vector>
     36 
     37 #include "jni.h"
     38 #include "nativehelper/scoped_local_ref.h"
     39 #include "nativehelper/scoped_utf_chars.h"
     40 
     41 #include "art_jvmti.h"
     42 #include "runtime.h"
     43 #include "thread-current-inl.h"
     44 #include "ti_phase.h"
     45 #include "well_known_classes.h"
     46 
     47 namespace openjdkjvmti {
     48 
     49 // Hardcoded properties. Tests ensure that these are consistent with libcore's view, as seen
     50 // in System.java and AndroidHardcodedSystemProperties.java.
     51 static constexpr const char* kProperties[][2] = {
     52     // Recommended by the spec.
     53     { "java.vm.vendor", "The Android Project" },
     54     { "java.vm.version", "2.1.0" },  // This is Runtime::GetVersion().
     55     { "java.vm.name", "Dalvik" },
     56     // Android does not provide java.vm.info.
     57     //
     58     // These are other values provided by AndroidHardcodedSystemProperties.
     59     { "java.class.version", "50.0" },
     60     { "java.version", "0" },
     61     { "java.compiler", "" },
     62     { "java.ext.dirs", "" },
     63 
     64     { "java.specification.name", "Dalvik Core Library" },
     65     { "java.specification.vendor", "The Android Project" },
     66     { "java.specification.version", "0.9" },
     67 
     68     { "java.vendor", "The Android Project" },
     69     { "java.vendor.url", "http://www.android.com/" },
     70     { "java.vm.name", "Dalvik" },
     71     { "java.vm.specification.name", "Dalvik Virtual Machine Specification" },
     72     { "java.vm.specification.vendor", "The Android Project" },
     73     { "java.vm.specification.version", "0.9" },
     74     { "java.vm.vendor", "The Android Project" },
     75 
     76     { "java.vm.vendor.url", "http://www.android.com/" },
     77 
     78     { "java.net.preferIPv6Addresses", "false" },
     79 
     80     { "file.encoding", "UTF-8" },
     81 
     82     { "file.separator", "/" },
     83     { "line.separator", "\n" },
     84     { "path.separator", ":" },
     85 
     86     { "os.name", "Linux" },
     87 };
     88 static constexpr size_t kPropertiesSize = arraysize(kProperties);
     89 static constexpr const char* kPropertyLibraryPath = "java.library.path";
     90 static constexpr const char* kPropertyClassPath = "java.class.path";
     91 
     92 jvmtiError PropertiesUtil::GetSystemProperties(jvmtiEnv* env,
     93                                                jint* count_ptr,
     94                                                char*** property_ptr) {
     95   if (count_ptr == nullptr || property_ptr == nullptr) {
     96     return ERR(NULL_POINTER);
     97   }
     98   jvmtiError array_alloc_result;
     99   JvmtiUniquePtr<char*[]> array_data_ptr = AllocJvmtiUniquePtr<char*[]>(env,
    100                                                                         kPropertiesSize + 2,
    101                                                                         &array_alloc_result);
    102   if (array_data_ptr == nullptr) {
    103     return array_alloc_result;
    104   }
    105 
    106   std::vector<JvmtiUniquePtr<char[]>> property_copies;
    107 
    108   {
    109     jvmtiError libpath_result;
    110     JvmtiUniquePtr<char[]> libpath_data = CopyString(env, kPropertyLibraryPath, &libpath_result);
    111     if (libpath_data == nullptr) {
    112       return libpath_result;
    113     }
    114     array_data_ptr.get()[0] = libpath_data.get();
    115     property_copies.push_back(std::move(libpath_data));
    116   }
    117 
    118   {
    119     jvmtiError classpath_result;
    120     JvmtiUniquePtr<char[]> classpath_data = CopyString(env, kPropertyClassPath, &classpath_result);
    121     if (classpath_data == nullptr) {
    122       return classpath_result;
    123     }
    124     array_data_ptr.get()[1] = classpath_data.get();
    125     property_copies.push_back(std::move(classpath_data));
    126   }
    127 
    128   for (size_t i = 0; i != kPropertiesSize; ++i) {
    129     jvmtiError data_result;
    130     JvmtiUniquePtr<char[]> data = CopyString(env, kProperties[i][0], &data_result);
    131     if (data == nullptr) {
    132       return data_result;
    133     }
    134     array_data_ptr.get()[i + 2] = data.get();
    135     property_copies.push_back(std::move(data));
    136   }
    137 
    138   // Everything is OK, release the data.
    139   *count_ptr = kPropertiesSize + 2;
    140   *property_ptr = array_data_ptr.release();
    141   for (auto& uptr : property_copies) {
    142     uptr.release();
    143   }
    144 
    145   return ERR(NONE);
    146 }
    147 
    148 static jvmtiError Copy(jvmtiEnv* env, const char* in, char** out) {
    149   jvmtiError result;
    150   JvmtiUniquePtr<char[]> data = CopyString(env, in, &result);
    151   *out = data.release();
    152   return result;
    153 }
    154 
    155 // See dalvik_system_VMRuntime.cpp.
    156 static const char* DefaultToDot(const std::string& class_path) {
    157   return class_path.empty() ? "." : class_path.c_str();
    158 }
    159 
    160 // Handle kPropertyLibraryPath.
    161 static jvmtiError GetLibraryPath(jvmtiEnv* env, char** value_ptr) {
    162   const std::vector<std::string>& runtime_props = art::Runtime::Current()->GetProperties();
    163   for (const std::string& prop_assignment : runtime_props) {
    164     size_t assign_pos = prop_assignment.find('=');
    165     if (assign_pos != std::string::npos && assign_pos > 0) {
    166       if (prop_assignment.substr(0, assign_pos) == kPropertyLibraryPath) {
    167         return Copy(env, prop_assignment.substr(assign_pos + 1).c_str(), value_ptr);
    168       }
    169     }
    170   }
    171   if (!PhaseUtil::IsLivePhase()) {
    172     return ERR(NOT_AVAILABLE);
    173   }
    174   // We expect this call to be rare. So don't optimize.
    175   DCHECK(art::Thread::Current() != nullptr);
    176   JNIEnv* jni_env = art::Thread::Current()->GetJniEnv();
    177   jmethodID get_prop = jni_env->GetStaticMethodID(art::WellKnownClasses::java_lang_System,
    178                                                   "getProperty",
    179                                                   "(Ljava/lang/String;)Ljava/lang/String;");
    180   CHECK(get_prop != nullptr);
    181 
    182   ScopedLocalRef<jobject> input_str(jni_env, jni_env->NewStringUTF(kPropertyLibraryPath));
    183   if (input_str.get() == nullptr) {
    184     jni_env->ExceptionClear();
    185     return ERR(OUT_OF_MEMORY);
    186   }
    187 
    188   ScopedLocalRef<jobject> prop_res(
    189       jni_env, jni_env->CallStaticObjectMethod(art::WellKnownClasses::java_lang_System,
    190                                                get_prop,
    191                                                input_str.get()));
    192   if (jni_env->ExceptionCheck() == JNI_TRUE) {
    193     jni_env->ExceptionClear();
    194     return ERR(INTERNAL);
    195   }
    196   if (prop_res.get() == nullptr) {
    197     *value_ptr = nullptr;
    198     return ERR(NONE);
    199   }
    200 
    201   ScopedUtfChars chars(jni_env, reinterpret_cast<jstring>(prop_res.get()));
    202   return Copy(env, chars.c_str(), value_ptr);
    203 }
    204 
    205 jvmtiError PropertiesUtil::GetSystemProperty(jvmtiEnv* env,
    206                                              const char* property,
    207                                              char** value_ptr) {
    208   if (property == nullptr || value_ptr == nullptr) {
    209     return ERR(NULL_POINTER);
    210   }
    211 
    212   if (strcmp(property, kPropertyLibraryPath) == 0) {
    213     return GetLibraryPath(env, value_ptr);
    214   }
    215 
    216   if (strcmp(property, kPropertyClassPath) == 0) {
    217     return Copy(env, DefaultToDot(art::Runtime::Current()->GetClassPathString()), value_ptr);
    218   }
    219 
    220   for (size_t i = 0; i != kPropertiesSize; ++i) {
    221     if (strcmp(property, kProperties[i][0]) == 0) {
    222       return Copy(env, kProperties[i][1], value_ptr);
    223     }
    224   }
    225 
    226   return ERR(NOT_AVAILABLE);
    227 }
    228 
    229 jvmtiError PropertiesUtil::SetSystemProperty(jvmtiEnv* env ATTRIBUTE_UNUSED,
    230                                              const char* property ATTRIBUTE_UNUSED,
    231                                              const char* value ATTRIBUTE_UNUSED) {
    232   // We do not allow manipulation of any property here.
    233   return ERR(NOT_AVAILABLE);
    234 }
    235 
    236 }  // namespace openjdkjvmti
    237