1 /*
2 * Copyright (c) 2003, 2025, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "classfile/classLoader.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "classfile/vmClasses.hpp"
28 #include "compiler/compileBroker.hpp"
29 #include "gc/shared/collectedHeap.hpp"
30 #include "jmm.h"
31 #include "memory/allocation.inline.hpp"
32 #include "memory/iterator.hpp"
33 #include "memory/oopFactory.hpp"
34 #include "memory/resourceArea.hpp"
35 #include "memory/universe.hpp"
36 #include "oops/klass.hpp"
37 #include "oops/klass.inline.hpp"
38 #include "oops/objArrayKlass.hpp"
39 #include "oops/objArrayOop.inline.hpp"
40 #include "oops/oop.inline.hpp"
41 #include "oops/oopHandle.inline.hpp"
42 #include "oops/typeArrayOop.inline.hpp"
43 #include "runtime/flags/jvmFlag.hpp"
44 #include "runtime/globals.hpp"
45 #include "runtime/handles.inline.hpp"
46 #include "runtime/interfaceSupport.inline.hpp"
47 #include "runtime/javaCalls.hpp"
48 #include "runtime/jniHandles.inline.hpp"
49 #include "runtime/mutexLocker.hpp"
50 #include "runtime/notificationThread.hpp"
51 #include "runtime/os.hpp"
52 #include "runtime/thread.inline.hpp"
53 #include "runtime/threads.hpp"
54 #include "runtime/threadSMR.hpp"
55 #include "runtime/vmOperations.hpp"
56 #include "services/classLoadingService.hpp"
57 #include "services/cpuTimeUsage.hpp"
58 #include "services/diagnosticCommand.hpp"
59 #include "services/diagnosticFramework.hpp"
60 #include "services/finalizerService.hpp"
1426
1427 JavaThread* java_thread = nullptr;
1428 if (thread_id == 0) {
1429 // current thread
1430 return os::current_thread_cpu_time();
1431 } else {
1432 ThreadsListHandle tlh;
1433 java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
1434 if (is_platform_thread(java_thread)) {
1435 return os::thread_cpu_time((Thread*) java_thread);
1436 }
1437 }
1438 return -1;
1439 JVM_END
1440
1441 // Returns a String array of all VM global flag names
1442 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1443 // last flag entry is always null, so subtract 1
1444 int nFlags = (int) JVMFlag::numFlags - 1;
1445 // allocate a temp array
1446 objArrayOop r = oopFactory::new_objArray(vmClasses::String_klass(),
1447 nFlags, CHECK_NULL);
1448 objArrayHandle flags_ah(THREAD, r);
1449 int num_entries = 0;
1450 for (int i = 0; i < nFlags; i++) {
1451 JVMFlag* flag = &JVMFlag::flags[i];
1452 // Exclude develop flags in product builds.
1453 if (flag->is_constant_in_binary()) {
1454 continue;
1455 }
1456 // Exclude the locked (experimental, diagnostic) flags
1457 if (flag->is_unlocked() || flag->is_unlocker()) {
1458 Handle s = java_lang_String::create_from_str(flag->name(), CHECK_NULL);
1459 flags_ah->obj_at_put(num_entries, s());
1460 num_entries++;
1461 }
1462 }
1463
1464 if (num_entries < nFlags) {
1465 // Return array of right length
1466 objArrayOop res = oopFactory::new_objArray(vmClasses::String_klass(), num_entries, CHECK_NULL);
1467 for(int i = 0; i < num_entries; i++) {
1468 res->obj_at_put(i, flags_ah->obj_at(i));
1469 }
1470 return (jobjectArray)JNIHandles::make_local(THREAD, res);
1471 }
1472
1473 return (jobjectArray)JNIHandles::make_local(THREAD, flags_ah());
1474 JVM_END
1475
1476 // Utility function used by jmm_GetVMGlobals. Returns false if flag type
1477 // can't be determined, true otherwise. If false is returned, then *global
1478 // will be incomplete and invalid.
1479 static bool add_global_entry(Handle name, jmmVMGlobal *global, JVMFlag *flag, TRAPS) {
1480 Handle flag_name;
1481 if (name() == nullptr) {
1482 flag_name = java_lang_String::create_from_str(flag->name(), CHECK_false);
1483 } else {
1484 flag_name = name;
1485 }
1486 global->name = (jstring)JNIHandles::make_local(THREAD, flag_name());
1552 // Fill globals array of count length with jmmVMGlobal entries
1553 // specified by names. If names == null, fill globals array
1554 // with all Flags. Return value is number of entries
1555 // created in globals.
1556 // If a JVMFlag with a given name in an array element does not
1557 // exist, globals[i].name will be set to null.
1558 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1559 jobjectArray names,
1560 jmmVMGlobal *globals,
1561 jint count))
1562
1563
1564 if (globals == nullptr) {
1565 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1566 }
1567
1568 ResourceMark rm(THREAD);
1569
1570 if (names != nullptr) {
1571 // return the requested globals
1572 objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names));
1573 objArrayHandle names_ah(THREAD, ta);
1574 // Make sure we have a String array
1575 Klass* element_klass = ObjArrayKlass::cast(names_ah->klass())->element_klass();
1576 if (element_klass != vmClasses::String_klass()) {
1577 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1578 "Array element type is not String class", 0);
1579 }
1580
1581 int names_length = names_ah->length();
1582 int num_entries = 0;
1583 for (int i = 0; i < names_length && i < count; i++) {
1584 oop s = names_ah->obj_at(i);
1585 if (s == nullptr) {
1586 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1587 }
1588
1589 Handle sh(THREAD, s);
1590 char* str = java_lang_String::as_utf8_string(s);
1591 JVMFlag* flag = JVMFlag::find_flag(str);
1592 if (flag != nullptr &&
1593 add_global_entry(sh, &globals[i], flag, THREAD)) {
1594 num_entries++;
1595 } else {
1979 ResourceMark rm(THREAD);
1980 GrowableArray<const char *>* dcmd_list = DCmdFactory::DCmd_list(DCmd_Source_MBean);
1981 objArrayOop cmd_array_oop = oopFactory::new_objArray(vmClasses::String_klass(),
1982 dcmd_list->length(), CHECK_NULL);
1983 objArrayHandle cmd_array(THREAD, cmd_array_oop);
1984 for (int i = 0; i < dcmd_list->length(); i++) {
1985 oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL);
1986 cmd_array->obj_at_put(i, cmd_name);
1987 }
1988 return (jobjectArray) JNIHandles::make_local(THREAD, cmd_array());
1989 JVM_END
1990
1991 JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
1992 dcmdInfo* infoArray))
1993 if (cmds == nullptr || infoArray == nullptr) {
1994 THROW(vmSymbols::java_lang_NullPointerException());
1995 }
1996
1997 ResourceMark rm(THREAD);
1998
1999 objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(cmds));
2000 objArrayHandle cmds_ah(THREAD, ca);
2001
2002 // Make sure we have a String array
2003 Klass* element_klass = ObjArrayKlass::cast(cmds_ah->klass())->element_klass();
2004 if (element_klass != vmClasses::String_klass()) {
2005 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2006 "Array element type is not String class");
2007 }
2008
2009 GrowableArray<DCmdInfo *>* info_list = DCmdFactory::DCmdInfo_list(DCmd_Source_MBean);
2010
2011 int num_cmds = cmds_ah->length();
2012 for (int i = 0; i < num_cmds; i++) {
2013 oop cmd = cmds_ah->obj_at(i);
2014 if (cmd == nullptr) {
2015 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2016 "Command name cannot be null.");
2017 }
2018 char* cmd_name = java_lang_String::as_utf8_string(cmd);
2019 if (cmd_name == nullptr) {
2020 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2021 "Command name cannot be null.");
2022 }
2023 int pos = info_list->find_if([&](DCmdInfo* info) {
|
1 /*
2 * Copyright (c) 2003, 2026, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "classfile/classLoader.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "classfile/vmClasses.hpp"
28 #include "compiler/compileBroker.hpp"
29 #include "gc/shared/collectedHeap.hpp"
30 #include "jmm.h"
31 #include "memory/allocation.inline.hpp"
32 #include "memory/iterator.hpp"
33 #include "memory/oopFactory.hpp"
34 #include "memory/resourceArea.hpp"
35 #include "memory/universe.hpp"
36 #include "oops/klass.hpp"
37 #include "oops/klass.inline.hpp"
38 #include "oops/objArrayKlass.hpp"
39 #include "oops/objArrayOop.inline.hpp"
40 #include "oops/oop.inline.hpp"
41 #include "oops/oopCast.inline.hpp"
42 #include "oops/oopHandle.inline.hpp"
43 #include "oops/typeArrayOop.inline.hpp"
44 #include "runtime/flags/jvmFlag.hpp"
45 #include "runtime/globals.hpp"
46 #include "runtime/handles.inline.hpp"
47 #include "runtime/interfaceSupport.inline.hpp"
48 #include "runtime/javaCalls.hpp"
49 #include "runtime/jniHandles.inline.hpp"
50 #include "runtime/mutexLocker.hpp"
51 #include "runtime/notificationThread.hpp"
52 #include "runtime/os.hpp"
53 #include "runtime/thread.inline.hpp"
54 #include "runtime/threads.hpp"
55 #include "runtime/threadSMR.hpp"
56 #include "runtime/vmOperations.hpp"
57 #include "services/classLoadingService.hpp"
58 #include "services/cpuTimeUsage.hpp"
59 #include "services/diagnosticCommand.hpp"
60 #include "services/diagnosticFramework.hpp"
61 #include "services/finalizerService.hpp"
1427
1428 JavaThread* java_thread = nullptr;
1429 if (thread_id == 0) {
1430 // current thread
1431 return os::current_thread_cpu_time();
1432 } else {
1433 ThreadsListHandle tlh;
1434 java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
1435 if (is_platform_thread(java_thread)) {
1436 return os::thread_cpu_time((Thread*) java_thread);
1437 }
1438 }
1439 return -1;
1440 JVM_END
1441
1442 // Returns a String array of all VM global flag names
1443 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1444 // last flag entry is always null, so subtract 1
1445 int nFlags = (int) JVMFlag::numFlags - 1;
1446 // allocate a temp array
1447 refArrayOop r = oopFactory::new_refArray(vmClasses::String_klass(),
1448 nFlags,
1449 CHECK_NULL);
1450 refArrayHandle flags_ah(THREAD, r);
1451 int num_entries = 0;
1452 for (int i = 0; i < nFlags; i++) {
1453 JVMFlag* flag = &JVMFlag::flags[i];
1454 // Exclude develop flags in product builds.
1455 if (flag->is_constant_in_binary()) {
1456 continue;
1457 }
1458 // Exclude the locked (experimental, diagnostic) flags
1459 if (flag->is_unlocked() || flag->is_unlocker()) {
1460 Handle s = java_lang_String::create_from_str(flag->name(), CHECK_NULL);
1461 flags_ah->obj_at_put(num_entries, s());
1462 num_entries++;
1463 }
1464 }
1465
1466 if (num_entries < nFlags) {
1467 // Return array of right length
1468 refArrayOop res = oopFactory::new_refArray(vmClasses::String_klass(), num_entries, CHECK_NULL);
1469 for(int i = 0; i < num_entries; i++) {
1470 res->obj_at_put(i, flags_ah->obj_at(i));
1471 }
1472 return (jobjectArray)JNIHandles::make_local(THREAD, res);
1473 }
1474
1475 return (jobjectArray)JNIHandles::make_local(THREAD, flags_ah());
1476 JVM_END
1477
1478 // Utility function used by jmm_GetVMGlobals. Returns false if flag type
1479 // can't be determined, true otherwise. If false is returned, then *global
1480 // will be incomplete and invalid.
1481 static bool add_global_entry(Handle name, jmmVMGlobal *global, JVMFlag *flag, TRAPS) {
1482 Handle flag_name;
1483 if (name() == nullptr) {
1484 flag_name = java_lang_String::create_from_str(flag->name(), CHECK_false);
1485 } else {
1486 flag_name = name;
1487 }
1488 global->name = (jstring)JNIHandles::make_local(THREAD, flag_name());
1554 // Fill globals array of count length with jmmVMGlobal entries
1555 // specified by names. If names == null, fill globals array
1556 // with all Flags. Return value is number of entries
1557 // created in globals.
1558 // If a JVMFlag with a given name in an array element does not
1559 // exist, globals[i].name will be set to null.
1560 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1561 jobjectArray names,
1562 jmmVMGlobal *globals,
1563 jint count))
1564
1565
1566 if (globals == nullptr) {
1567 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1568 }
1569
1570 ResourceMark rm(THREAD);
1571
1572 if (names != nullptr) {
1573 // return the requested globals
1574 refArrayOop ta = oop_cast<refArrayOop>(JNIHandles::resolve_non_null(names));
1575 refArrayHandle names_ah(THREAD, ta);
1576 // Make sure we have a String array
1577 Klass* element_klass = RefArrayKlass::cast(names_ah->klass())->element_klass();
1578 if (element_klass != vmClasses::String_klass()) {
1579 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1580 "Array element type is not String class", 0);
1581 }
1582
1583 int names_length = names_ah->length();
1584 int num_entries = 0;
1585 for (int i = 0; i < names_length && i < count; i++) {
1586 oop s = names_ah->obj_at(i);
1587 if (s == nullptr) {
1588 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1589 }
1590
1591 Handle sh(THREAD, s);
1592 char* str = java_lang_String::as_utf8_string(s);
1593 JVMFlag* flag = JVMFlag::find_flag(str);
1594 if (flag != nullptr &&
1595 add_global_entry(sh, &globals[i], flag, THREAD)) {
1596 num_entries++;
1597 } else {
1981 ResourceMark rm(THREAD);
1982 GrowableArray<const char *>* dcmd_list = DCmdFactory::DCmd_list(DCmd_Source_MBean);
1983 objArrayOop cmd_array_oop = oopFactory::new_objArray(vmClasses::String_klass(),
1984 dcmd_list->length(), CHECK_NULL);
1985 objArrayHandle cmd_array(THREAD, cmd_array_oop);
1986 for (int i = 0; i < dcmd_list->length(); i++) {
1987 oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL);
1988 cmd_array->obj_at_put(i, cmd_name);
1989 }
1990 return (jobjectArray) JNIHandles::make_local(THREAD, cmd_array());
1991 JVM_END
1992
1993 JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
1994 dcmdInfo* infoArray))
1995 if (cmds == nullptr || infoArray == nullptr) {
1996 THROW(vmSymbols::java_lang_NullPointerException());
1997 }
1998
1999 ResourceMark rm(THREAD);
2000
2001 refArrayOop ca = oop_cast<refArrayOop>(JNIHandles::resolve_non_null(cmds));
2002 refArrayHandle cmds_ah(THREAD, ca);
2003
2004 // Make sure we have a String array
2005 Klass* element_klass = RefArrayKlass::cast(cmds_ah->klass())->element_klass();
2006 if (element_klass != vmClasses::String_klass()) {
2007 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2008 "Array element type is not String class");
2009 }
2010
2011 GrowableArray<DCmdInfo *>* info_list = DCmdFactory::DCmdInfo_list(DCmd_Source_MBean);
2012
2013 int num_cmds = cmds_ah->length();
2014 for (int i = 0; i < num_cmds; i++) {
2015 oop cmd = cmds_ah->obj_at(i);
2016 if (cmd == nullptr) {
2017 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2018 "Command name cannot be null.");
2019 }
2020 char* cmd_name = java_lang_String::as_utf8_string(cmd);
2021 if (cmd_name == nullptr) {
2022 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2023 "Command name cannot be null.");
2024 }
2025 int pos = info_list->find_if([&](DCmdInfo* info) {
|