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