From 59f4d10103db21f107067f0e1253d9be748dfee8 Mon Sep 17 00:00:00 2001 From: SuccessZhang Date: Mon, 26 Apr 2021 20:15:13 +0800 Subject: [PATCH 01/31] add basic vmtools code. #1698 --- .gitignore | 2 + arthas-beans/README_CN.md | 62 + arthas-beans/pom.xml | 211 ++ .../main/java/com/vdian/vclub/JvmUtils.java | 66 + arthas-beans/src/main/native/CMakeLists.txt | 18 + .../main/native/head/classfile_constants.h | 560 ++++ arthas-beans/src/main/native/head/jawt.h | 299 ++ .../src/main/native/head/jdwpTransport.h | 259 ++ arthas-beans/src/main/native/head/jni.h | 1960 +++++++++++++ arthas-beans/src/main/native/head/jvmti.h | 2534 +++++++++++++++++ arthas-beans/src/main/native/head/jvmticmlr.h | 115 + .../src/main/native/head/linux/jawt_md.h | 61 + .../src/main/native/head/linux/jni_md.h | 51 + .../src/main/native/head/macos/jawt_md.h | 77 + .../src/main/native/head/macos/jni_md.h | 42 + .../head/windows/AccessBridgeCallbacks.h | 96 + .../native/head/windows/AccessBridgeCalls.c | 1131 ++++++++ .../native/head/windows/AccessBridgeCalls.h | 706 +++++ .../head/windows/AccessBridgePackages.h | 2215 ++++++++++++++ .../src/main/native/head/windows/jawt_md.h | 59 + .../src/main/native/head/windows/jni_md.h | 37 + .../native/include/com_vdian_vclub_JvmUtils.h | 61 + .../src/main/native/src/jni-library.cpp | 198 ++ .../java/com/vdian/vclub/JvmUtilsTest.java | 48 + pom.xml | 6 + 25 files changed, 10874 insertions(+) create mode 100644 arthas-beans/README_CN.md create mode 100644 arthas-beans/pom.xml create mode 100644 arthas-beans/src/main/java/com/vdian/vclub/JvmUtils.java create mode 100644 arthas-beans/src/main/native/CMakeLists.txt create mode 100755 arthas-beans/src/main/native/head/classfile_constants.h create mode 100755 arthas-beans/src/main/native/head/jawt.h create mode 100755 arthas-beans/src/main/native/head/jdwpTransport.h create mode 100755 arthas-beans/src/main/native/head/jni.h create mode 100755 arthas-beans/src/main/native/head/jvmti.h create mode 100755 arthas-beans/src/main/native/head/jvmticmlr.h create mode 100644 arthas-beans/src/main/native/head/linux/jawt_md.h create mode 100644 arthas-beans/src/main/native/head/linux/jni_md.h create mode 100644 arthas-beans/src/main/native/head/macos/jawt_md.h create mode 100644 arthas-beans/src/main/native/head/macos/jni_md.h create mode 100755 arthas-beans/src/main/native/head/windows/AccessBridgeCallbacks.h create mode 100755 arthas-beans/src/main/native/head/windows/AccessBridgeCalls.c create mode 100755 arthas-beans/src/main/native/head/windows/AccessBridgeCalls.h create mode 100755 arthas-beans/src/main/native/head/windows/AccessBridgePackages.h create mode 100755 arthas-beans/src/main/native/head/windows/jawt_md.h create mode 100755 arthas-beans/src/main/native/head/windows/jni_md.h create mode 100644 arthas-beans/src/main/native/include/com_vdian_vclub_JvmUtils.h create mode 100644 arthas-beans/src/main/native/src/jni-library.cpp create mode 100644 arthas-beans/src/test/java/com/vdian/vclub/JvmUtilsTest.java diff --git a/.gitignore b/.gitignore index aa22d9532..ef2356edb 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ dependency-reduced-pom.xml pom.xml.versionsBackup .pmd **/.flattened-pom.xml +**/.idea/** +**/cmake-build-debug/** diff --git a/arthas-beans/README_CN.md b/arthas-beans/README_CN.md new file mode 100644 index 000000000..4ea4b8795 --- /dev/null +++ b/arthas-beans/README_CN.md @@ -0,0 +1,62 @@ +##step1 在您的pom.xml中增加profile配置 +``` + + + + macos + + + mac + + + + macos + + + + + + linux + + + linux + + + + linux + + + + + + windows + + + windows + + + + windows + + + +``` +##step2 在您的pom.xml中引入依赖 +PS:一定要配置好profile,不然无法自动生成``配置。 +``` + + com.taobao.arthas + mana-pool-analyzer + ${arthas.vision} + ${os_family}-${os.arch} + +``` + +##step3 如果没有合适的版本 +1. 如果是32位的操作系统,不好意思,目前暂不支持。 + +2. 如果是64位操作系统,请先尝试`mvn clean compile package install -DskipTests=true -U`把依赖安装到本地; + +3. 如果报错,请先确保您本地的g++编译器能够正常工作,再重新尝试`mvn clean compile package install -DskipTests=true -U`; + +如有问题请联系`1936978077@qq.com`。 diff --git a/arthas-beans/pom.xml b/arthas-beans/pom.xml new file mode 100644 index 000000000..51628db14 --- /dev/null +++ b/arthas-beans/pom.xml @@ -0,0 +1,211 @@ + + + 4.0.0 + + arthas-all + com.taobao.arthas + ${revision} + ../pom.xml + + arthas-beans + arthas-beans + + + + + macos-x86_64 + + + mac + x86_64 + + + + macos + -m64 + libArthasJniLibrary.dylib + + + + macos-amd64 + + + mac + amd64 + + + + macos + -m64 + libArthasJniLibrary.dylib + + + + + + linux-x86_64 + + + linux + x86_64 + + + + linux + -m64 + libArthasJniLibrary.so + + + + linux-amd64 + + + linux + amd64 + + + + linux + -m64 + libArthasJniLibrary.so + + + + + + windows-x86_64 + + + windows + x86_64 + + + + windows + -m64 + ArthasJniLibrary.dll + + + + windows-amd64 + + + windows + amd64 + + + + windows + -m64 + ArthasJniLibrary.dll + + + + + + arthas-beans + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + UTF-8 + true + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + default-jar + package + + jar + + + ${os_name}-${os.arch} + ${project.build.directory}/classes + + + + + + org.codehaus.mojo + native-maven-plugin + 1.0-alpha-11 + true + + ${project.basedir}/src/main/native/head + ${os_name} + + + src/main/native/src + + jni-library.cpp + + + + src/main/native/include + + + + generic-classic + g++ + + ${os_arch_option} + -fpic + -shared + -o + + + target + g++ + + ${os_arch_option} + -fpic + -shared + -o + + + -o ${project.build.directory}/classes/${lib_name} + + + + + javah + compile + + initialize + compile + link + + + + + + + + + + com.taobao.arthas + arthas-common + ${project.version} + + + org.scijava + native-lib-loader + + + junit + junit + test + + + \ No newline at end of file diff --git a/arthas-beans/src/main/java/com/vdian/vclub/JvmUtils.java b/arthas-beans/src/main/java/com/vdian/vclub/JvmUtils.java new file mode 100644 index 000000000..0f707984a --- /dev/null +++ b/arthas-beans/src/main/java/com/vdian/vclub/JvmUtils.java @@ -0,0 +1,66 @@ +package com.vdian.vclub; + +import com.taobao.arthas.common.AnsiLog; +import org.scijava.nativelib.NativeLoader; + +import java.util.ArrayList; + +/** + * @author ZhangZiCheng 2021-02-12 + * @since 3.5.1 + */ +public class JvmUtils { + + /** + * 不要修改jni-lib的名称 + */ + private final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; + + static { + try { + NativeLoader.loadLibrary(JNI_LIBRARY_NAME); + AnsiLog.warn("checkResult->" + check() + ", jni-lib available !"); + } catch (Throwable t) { + AnsiLog.error("load jni-lib failed:" + t.getMessage(), t); + } + } + + /** + * 检测jni-lib是否正常,如果正常,应该输出OK + */ + public static native String check(); + + /** + * 获取某个class在jvm中当前所有存活实例 + */ + public static native ArrayList getInstances(Class klass); + + /** + * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte + */ + public static native long sumInstanceSize(Class klass); + + /** + * 获取某个实例的占用内存,单位:Byte + */ + public static native long getInstanceSize(Object instance); + + /** + * 统计某个class在jvm中当前所有存活实例的总个数 + */ + public static native long countInstances(Class klass); + + /** + * 获取所有已加载的类 + */ + public static native ArrayList> getAllLoadedClasses(); + + /** + * 包括小类型(如int) + */ + @SuppressWarnings("all") + public static ArrayList getAllClasses() { + return getInstances(Class.class); + } + +} diff --git a/arthas-beans/src/main/native/CMakeLists.txt b/arthas-beans/src/main/native/CMakeLists.txt new file mode 100644 index 000000000..68c624afb --- /dev/null +++ b/arthas-beans/src/main/native/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.17) +project(arthas-native) + +set(CMAKE_CXX_STANDARD 14) + +add_library(jni-lib SHARED src/jni-library.cpp) + +#使用环境变量来include,把不同系统的兼容问题交给jdk解决 +include_directories("include") +include_directories(head) + +IF (WIN32) + include_directories(head/windows) +ELSEIF (APPLE) + include_directories(head/macos) +ELSEIF (common/linux) + include_directories(head/linux) +ENDIF () \ No newline at end of file diff --git a/arthas-beans/src/main/native/head/classfile_constants.h b/arthas-beans/src/main/native/head/classfile_constants.h new file mode 100755 index 000000000..e5c20cd9a --- /dev/null +++ b/arthas-beans/src/main/native/head/classfile_constants.h @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef CLASSFILE_CONSTANTS_H +#define CLASSFILE_CONSTANTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Classfile version number for this information */ +#define JVM_CLASSFILE_MAJOR_VERSION 52 +#define JVM_CLASSFILE_MINOR_VERSION 0 + +/* Flags */ + +enum { + JVM_ACC_PUBLIC = 0x0001, + JVM_ACC_PRIVATE = 0x0002, + JVM_ACC_PROTECTED = 0x0004, + JVM_ACC_STATIC = 0x0008, + JVM_ACC_FINAL = 0x0010, + JVM_ACC_SYNCHRONIZED = 0x0020, + JVM_ACC_SUPER = 0x0020, + JVM_ACC_VOLATILE = 0x0040, + JVM_ACC_BRIDGE = 0x0040, + JVM_ACC_TRANSIENT = 0x0080, + JVM_ACC_VARARGS = 0x0080, + JVM_ACC_NATIVE = 0x0100, + JVM_ACC_INTERFACE = 0x0200, + JVM_ACC_ABSTRACT = 0x0400, + JVM_ACC_STRICT = 0x0800, + JVM_ACC_SYNTHETIC = 0x1000, + JVM_ACC_ANNOTATION = 0x2000, + JVM_ACC_ENUM = 0x4000 +}; + +/* Used in newarray instruction. */ + +enum { + JVM_T_BOOLEAN = 4, + JVM_T_CHAR = 5, + JVM_T_FLOAT = 6, + JVM_T_DOUBLE = 7, + JVM_T_BYTE = 8, + JVM_T_SHORT = 9, + JVM_T_INT = 10, + JVM_T_LONG = 11 +}; + +/* Constant Pool Entries */ + +enum { + JVM_CONSTANT_Utf8 = 1, + JVM_CONSTANT_Unicode = 2, /* unused */ + JVM_CONSTANT_Integer = 3, + JVM_CONSTANT_Float = 4, + JVM_CONSTANT_Long = 5, + JVM_CONSTANT_Double = 6, + JVM_CONSTANT_Class = 7, + JVM_CONSTANT_String = 8, + JVM_CONSTANT_Fieldref = 9, + JVM_CONSTANT_Methodref = 10, + JVM_CONSTANT_InterfaceMethodref = 11, + JVM_CONSTANT_NameAndType = 12, + JVM_CONSTANT_MethodHandle = 15, // JSR 292 + JVM_CONSTANT_MethodType = 16, // JSR 292 + JVM_CONSTANT_InvokeDynamic = 18 +}; + +/* JVM_CONSTANT_MethodHandle subtypes */ +enum { + JVM_REF_getField = 1, + JVM_REF_getStatic = 2, + JVM_REF_putField = 3, + JVM_REF_putStatic = 4, + JVM_REF_invokeVirtual = 5, + JVM_REF_invokeStatic = 6, + JVM_REF_invokeSpecial = 7, + JVM_REF_newInvokeSpecial = 8, + JVM_REF_invokeInterface = 9 +}; + +/* StackMapTable type item numbers */ + +enum { + JVM_ITEM_Top = 0, + JVM_ITEM_Integer = 1, + JVM_ITEM_Float = 2, + JVM_ITEM_Double = 3, + JVM_ITEM_Long = 4, + JVM_ITEM_Null = 5, + JVM_ITEM_UninitializedThis = 6, + JVM_ITEM_Object = 7, + JVM_ITEM_Uninitialized = 8 +}; + +/* Type signatures */ + +enum { + JVM_SIGNATURE_ARRAY = '[', + JVM_SIGNATURE_BYTE = 'B', + JVM_SIGNATURE_CHAR = 'C', + JVM_SIGNATURE_CLASS = 'L', + JVM_SIGNATURE_ENDCLASS = ';', + JVM_SIGNATURE_ENUM = 'E', + JVM_SIGNATURE_FLOAT = 'F', + JVM_SIGNATURE_DOUBLE = 'D', + JVM_SIGNATURE_FUNC = '(', + JVM_SIGNATURE_ENDFUNC = ')', + JVM_SIGNATURE_INT = 'I', + JVM_SIGNATURE_LONG = 'J', + JVM_SIGNATURE_SHORT = 'S', + JVM_SIGNATURE_VOID = 'V', + JVM_SIGNATURE_BOOLEAN = 'Z' +}; + +/* Opcodes */ + +enum { + JVM_OPC_nop = 0, + JVM_OPC_aconst_null = 1, + JVM_OPC_iconst_m1 = 2, + JVM_OPC_iconst_0 = 3, + JVM_OPC_iconst_1 = 4, + JVM_OPC_iconst_2 = 5, + JVM_OPC_iconst_3 = 6, + JVM_OPC_iconst_4 = 7, + JVM_OPC_iconst_5 = 8, + JVM_OPC_lconst_0 = 9, + JVM_OPC_lconst_1 = 10, + JVM_OPC_fconst_0 = 11, + JVM_OPC_fconst_1 = 12, + JVM_OPC_fconst_2 = 13, + JVM_OPC_dconst_0 = 14, + JVM_OPC_dconst_1 = 15, + JVM_OPC_bipush = 16, + JVM_OPC_sipush = 17, + JVM_OPC_ldc = 18, + JVM_OPC_ldc_w = 19, + JVM_OPC_ldc2_w = 20, + JVM_OPC_iload = 21, + JVM_OPC_lload = 22, + JVM_OPC_fload = 23, + JVM_OPC_dload = 24, + JVM_OPC_aload = 25, + JVM_OPC_iload_0 = 26, + JVM_OPC_iload_1 = 27, + JVM_OPC_iload_2 = 28, + JVM_OPC_iload_3 = 29, + JVM_OPC_lload_0 = 30, + JVM_OPC_lload_1 = 31, + JVM_OPC_lload_2 = 32, + JVM_OPC_lload_3 = 33, + JVM_OPC_fload_0 = 34, + JVM_OPC_fload_1 = 35, + JVM_OPC_fload_2 = 36, + JVM_OPC_fload_3 = 37, + JVM_OPC_dload_0 = 38, + JVM_OPC_dload_1 = 39, + JVM_OPC_dload_2 = 40, + JVM_OPC_dload_3 = 41, + JVM_OPC_aload_0 = 42, + JVM_OPC_aload_1 = 43, + JVM_OPC_aload_2 = 44, + JVM_OPC_aload_3 = 45, + JVM_OPC_iaload = 46, + JVM_OPC_laload = 47, + JVM_OPC_faload = 48, + JVM_OPC_daload = 49, + JVM_OPC_aaload = 50, + JVM_OPC_baload = 51, + JVM_OPC_caload = 52, + JVM_OPC_saload = 53, + JVM_OPC_istore = 54, + JVM_OPC_lstore = 55, + JVM_OPC_fstore = 56, + JVM_OPC_dstore = 57, + JVM_OPC_astore = 58, + JVM_OPC_istore_0 = 59, + JVM_OPC_istore_1 = 60, + JVM_OPC_istore_2 = 61, + JVM_OPC_istore_3 = 62, + JVM_OPC_lstore_0 = 63, + JVM_OPC_lstore_1 = 64, + JVM_OPC_lstore_2 = 65, + JVM_OPC_lstore_3 = 66, + JVM_OPC_fstore_0 = 67, + JVM_OPC_fstore_1 = 68, + JVM_OPC_fstore_2 = 69, + JVM_OPC_fstore_3 = 70, + JVM_OPC_dstore_0 = 71, + JVM_OPC_dstore_1 = 72, + JVM_OPC_dstore_2 = 73, + JVM_OPC_dstore_3 = 74, + JVM_OPC_astore_0 = 75, + JVM_OPC_astore_1 = 76, + JVM_OPC_astore_2 = 77, + JVM_OPC_astore_3 = 78, + JVM_OPC_iastore = 79, + JVM_OPC_lastore = 80, + JVM_OPC_fastore = 81, + JVM_OPC_dastore = 82, + JVM_OPC_aastore = 83, + JVM_OPC_bastore = 84, + JVM_OPC_castore = 85, + JVM_OPC_sastore = 86, + JVM_OPC_pop = 87, + JVM_OPC_pop2 = 88, + JVM_OPC_dup = 89, + JVM_OPC_dup_x1 = 90, + JVM_OPC_dup_x2 = 91, + JVM_OPC_dup2 = 92, + JVM_OPC_dup2_x1 = 93, + JVM_OPC_dup2_x2 = 94, + JVM_OPC_swap = 95, + JVM_OPC_iadd = 96, + JVM_OPC_ladd = 97, + JVM_OPC_fadd = 98, + JVM_OPC_dadd = 99, + JVM_OPC_isub = 100, + JVM_OPC_lsub = 101, + JVM_OPC_fsub = 102, + JVM_OPC_dsub = 103, + JVM_OPC_imul = 104, + JVM_OPC_lmul = 105, + JVM_OPC_fmul = 106, + JVM_OPC_dmul = 107, + JVM_OPC_idiv = 108, + JVM_OPC_ldiv = 109, + JVM_OPC_fdiv = 110, + JVM_OPC_ddiv = 111, + JVM_OPC_irem = 112, + JVM_OPC_lrem = 113, + JVM_OPC_frem = 114, + JVM_OPC_drem = 115, + JVM_OPC_ineg = 116, + JVM_OPC_lneg = 117, + JVM_OPC_fneg = 118, + JVM_OPC_dneg = 119, + JVM_OPC_ishl = 120, + JVM_OPC_lshl = 121, + JVM_OPC_ishr = 122, + JVM_OPC_lshr = 123, + JVM_OPC_iushr = 124, + JVM_OPC_lushr = 125, + JVM_OPC_iand = 126, + JVM_OPC_land = 127, + JVM_OPC_ior = 128, + JVM_OPC_lor = 129, + JVM_OPC_ixor = 130, + JVM_OPC_lxor = 131, + JVM_OPC_iinc = 132, + JVM_OPC_i2l = 133, + JVM_OPC_i2f = 134, + JVM_OPC_i2d = 135, + JVM_OPC_l2i = 136, + JVM_OPC_l2f = 137, + JVM_OPC_l2d = 138, + JVM_OPC_f2i = 139, + JVM_OPC_f2l = 140, + JVM_OPC_f2d = 141, + JVM_OPC_d2i = 142, + JVM_OPC_d2l = 143, + JVM_OPC_d2f = 144, + JVM_OPC_i2b = 145, + JVM_OPC_i2c = 146, + JVM_OPC_i2s = 147, + JVM_OPC_lcmp = 148, + JVM_OPC_fcmpl = 149, + JVM_OPC_fcmpg = 150, + JVM_OPC_dcmpl = 151, + JVM_OPC_dcmpg = 152, + JVM_OPC_ifeq = 153, + JVM_OPC_ifne = 154, + JVM_OPC_iflt = 155, + JVM_OPC_ifge = 156, + JVM_OPC_ifgt = 157, + JVM_OPC_ifle = 158, + JVM_OPC_if_icmpeq = 159, + JVM_OPC_if_icmpne = 160, + JVM_OPC_if_icmplt = 161, + JVM_OPC_if_icmpge = 162, + JVM_OPC_if_icmpgt = 163, + JVM_OPC_if_icmple = 164, + JVM_OPC_if_acmpeq = 165, + JVM_OPC_if_acmpne = 166, + JVM_OPC_goto = 167, + JVM_OPC_jsr = 168, + JVM_OPC_ret = 169, + JVM_OPC_tableswitch = 170, + JVM_OPC_lookupswitch = 171, + JVM_OPC_ireturn = 172, + JVM_OPC_lreturn = 173, + JVM_OPC_freturn = 174, + JVM_OPC_dreturn = 175, + JVM_OPC_areturn = 176, + JVM_OPC_return = 177, + JVM_OPC_getstatic = 178, + JVM_OPC_putstatic = 179, + JVM_OPC_getfield = 180, + JVM_OPC_putfield = 181, + JVM_OPC_invokevirtual = 182, + JVM_OPC_invokespecial = 183, + JVM_OPC_invokestatic = 184, + JVM_OPC_invokeinterface = 185, + JVM_OPC_invokedynamic = 186, + JVM_OPC_new = 187, + JVM_OPC_newarray = 188, + JVM_OPC_anewarray = 189, + JVM_OPC_arraylength = 190, + JVM_OPC_athrow = 191, + JVM_OPC_checkcast = 192, + JVM_OPC_instanceof = 193, + JVM_OPC_monitorenter = 194, + JVM_OPC_monitorexit = 195, + JVM_OPC_wide = 196, + JVM_OPC_multianewarray = 197, + JVM_OPC_ifnull = 198, + JVM_OPC_ifnonnull = 199, + JVM_OPC_goto_w = 200, + JVM_OPC_jsr_w = 201, + JVM_OPC_MAX = 201 +}; + +/* Opcode length initializer, use with something like: + * unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER; + */ +#define JVM_OPCODE_LENGTH_INITIALIZER { \ + 1, /* nop */ \ + 1, /* aconst_null */ \ + 1, /* iconst_m1 */ \ + 1, /* iconst_0 */ \ + 1, /* iconst_1 */ \ + 1, /* iconst_2 */ \ + 1, /* iconst_3 */ \ + 1, /* iconst_4 */ \ + 1, /* iconst_5 */ \ + 1, /* lconst_0 */ \ + 1, /* lconst_1 */ \ + 1, /* fconst_0 */ \ + 1, /* fconst_1 */ \ + 1, /* fconst_2 */ \ + 1, /* dconst_0 */ \ + 1, /* dconst_1 */ \ + 2, /* bipush */ \ + 3, /* sipush */ \ + 2, /* ldc */ \ + 3, /* ldc_w */ \ + 3, /* ldc2_w */ \ + 2, /* iload */ \ + 2, /* lload */ \ + 2, /* fload */ \ + 2, /* dload */ \ + 2, /* aload */ \ + 1, /* iload_0 */ \ + 1, /* iload_1 */ \ + 1, /* iload_2 */ \ + 1, /* iload_3 */ \ + 1, /* lload_0 */ \ + 1, /* lload_1 */ \ + 1, /* lload_2 */ \ + 1, /* lload_3 */ \ + 1, /* fload_0 */ \ + 1, /* fload_1 */ \ + 1, /* fload_2 */ \ + 1, /* fload_3 */ \ + 1, /* dload_0 */ \ + 1, /* dload_1 */ \ + 1, /* dload_2 */ \ + 1, /* dload_3 */ \ + 1, /* aload_0 */ \ + 1, /* aload_1 */ \ + 1, /* aload_2 */ \ + 1, /* aload_3 */ \ + 1, /* iaload */ \ + 1, /* laload */ \ + 1, /* faload */ \ + 1, /* daload */ \ + 1, /* aaload */ \ + 1, /* baload */ \ + 1, /* caload */ \ + 1, /* saload */ \ + 2, /* istore */ \ + 2, /* lstore */ \ + 2, /* fstore */ \ + 2, /* dstore */ \ + 2, /* astore */ \ + 1, /* istore_0 */ \ + 1, /* istore_1 */ \ + 1, /* istore_2 */ \ + 1, /* istore_3 */ \ + 1, /* lstore_0 */ \ + 1, /* lstore_1 */ \ + 1, /* lstore_2 */ \ + 1, /* lstore_3 */ \ + 1, /* fstore_0 */ \ + 1, /* fstore_1 */ \ + 1, /* fstore_2 */ \ + 1, /* fstore_3 */ \ + 1, /* dstore_0 */ \ + 1, /* dstore_1 */ \ + 1, /* dstore_2 */ \ + 1, /* dstore_3 */ \ + 1, /* astore_0 */ \ + 1, /* astore_1 */ \ + 1, /* astore_2 */ \ + 1, /* astore_3 */ \ + 1, /* iastore */ \ + 1, /* lastore */ \ + 1, /* fastore */ \ + 1, /* dastore */ \ + 1, /* aastore */ \ + 1, /* bastore */ \ + 1, /* castore */ \ + 1, /* sastore */ \ + 1, /* pop */ \ + 1, /* pop2 */ \ + 1, /* dup */ \ + 1, /* dup_x1 */ \ + 1, /* dup_x2 */ \ + 1, /* dup2 */ \ + 1, /* dup2_x1 */ \ + 1, /* dup2_x2 */ \ + 1, /* swap */ \ + 1, /* iadd */ \ + 1, /* ladd */ \ + 1, /* fadd */ \ + 1, /* dadd */ \ + 1, /* isub */ \ + 1, /* lsub */ \ + 1, /* fsub */ \ + 1, /* dsub */ \ + 1, /* imul */ \ + 1, /* lmul */ \ + 1, /* fmul */ \ + 1, /* dmul */ \ + 1, /* idiv */ \ + 1, /* ldiv */ \ + 1, /* fdiv */ \ + 1, /* ddiv */ \ + 1, /* irem */ \ + 1, /* lrem */ \ + 1, /* frem */ \ + 1, /* drem */ \ + 1, /* ineg */ \ + 1, /* lneg */ \ + 1, /* fneg */ \ + 1, /* dneg */ \ + 1, /* ishl */ \ + 1, /* lshl */ \ + 1, /* ishr */ \ + 1, /* lshr */ \ + 1, /* iushr */ \ + 1, /* lushr */ \ + 1, /* iand */ \ + 1, /* land */ \ + 1, /* ior */ \ + 1, /* lor */ \ + 1, /* ixor */ \ + 1, /* lxor */ \ + 3, /* iinc */ \ + 1, /* i2l */ \ + 1, /* i2f */ \ + 1, /* i2d */ \ + 1, /* l2i */ \ + 1, /* l2f */ \ + 1, /* l2d */ \ + 1, /* f2i */ \ + 1, /* f2l */ \ + 1, /* f2d */ \ + 1, /* d2i */ \ + 1, /* d2l */ \ + 1, /* d2f */ \ + 1, /* i2b */ \ + 1, /* i2c */ \ + 1, /* i2s */ \ + 1, /* lcmp */ \ + 1, /* fcmpl */ \ + 1, /* fcmpg */ \ + 1, /* dcmpl */ \ + 1, /* dcmpg */ \ + 3, /* ifeq */ \ + 3, /* ifne */ \ + 3, /* iflt */ \ + 3, /* ifge */ \ + 3, /* ifgt */ \ + 3, /* ifle */ \ + 3, /* if_icmpeq */ \ + 3, /* if_icmpne */ \ + 3, /* if_icmplt */ \ + 3, /* if_icmpge */ \ + 3, /* if_icmpgt */ \ + 3, /* if_icmple */ \ + 3, /* if_acmpeq */ \ + 3, /* if_acmpne */ \ + 3, /* goto */ \ + 3, /* jsr */ \ + 2, /* ret */ \ + 99, /* tableswitch */ \ + 99, /* lookupswitch */ \ + 1, /* ireturn */ \ + 1, /* lreturn */ \ + 1, /* freturn */ \ + 1, /* dreturn */ \ + 1, /* areturn */ \ + 1, /* return */ \ + 3, /* getstatic */ \ + 3, /* putstatic */ \ + 3, /* getfield */ \ + 3, /* putfield */ \ + 3, /* invokevirtual */ \ + 3, /* invokespecial */ \ + 3, /* invokestatic */ \ + 5, /* invokeinterface */ \ + 5, /* invokedynamic */ \ + 3, /* new */ \ + 2, /* newarray */ \ + 3, /* anewarray */ \ + 1, /* arraylength */ \ + 1, /* athrow */ \ + 3, /* checkcast */ \ + 3, /* instanceof */ \ + 1, /* monitorenter */ \ + 1, /* monitorexit */ \ + 0, /* wide */ \ + 4, /* multianewarray */ \ + 3, /* ifnull */ \ + 3, /* ifnonnull */ \ + 5, /* goto_w */ \ + 5 /* jsr_w */ \ +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* CLASSFILE_CONSTANTS */ diff --git a/arthas-beans/src/main/native/head/jawt.h b/arthas-beans/src/main/native/head/jawt.h new file mode 100755 index 000000000..f06e80713 --- /dev/null +++ b/arthas-beans/src/main/native/head/jawt.h @@ -0,0 +1,299 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JAWT_H_ +#define _JAVASOFT_JAWT_H_ + +#include "jni.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * AWT native interface (new in JDK 1.3) + * + * The AWT native interface allows a native C or C++ application a means + * by which to access native structures in AWT. This is to facilitate moving + * legacy C and C++ applications to Java and to target the needs of the + * community who, at present, wish to do their own native rendering to canvases + * for performance reasons. Standard extensions such as Java3D also require a + * means to access the underlying native data structures of AWT. + * + * There may be future extensions to this API depending on demand. + * + * A VM does not have to implement this API in order to pass the JCK. + * It is recommended, however, that this API is implemented on VMs that support + * standard extensions, such as Java3D. + * + * Since this is a native API, any program which uses it cannot be considered + * 100% pure java. + */ + +/* + * AWT Native Drawing Surface (JAWT_DrawingSurface). + * + * For each platform, there is a native drawing surface structure. This + * platform-specific structure can be found in jawt_md.h. It is recommended + * that additional platforms follow the same model. It is also recommended + * that VMs on Win32 and Solaris support the existing structures in jawt_md.h. + * + ******************* + * EXAMPLE OF USAGE: + ******************* + * + * In Win32, a programmer wishes to access the HWND of a canvas to perform + * native rendering into it. The programmer has declared the paint() method + * for their canvas subclass to be native: + * + * + * MyCanvas.java: + * + * import java.awt.*; + * + * public class MyCanvas extends Canvas { + * + * static { + * System.loadLibrary("mylib"); + * } + * + * public native void paint(Graphics g); + * } + * + * + * myfile.c: + * + * #include "jawt_md.h" + * #include + * + * JNIEXPORT void JNICALL + * Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics) + * { + * JAWT awt; + * JAWT_DrawingSurface* ds; + * JAWT_DrawingSurfaceInfo* dsi; + * JAWT_Win32DrawingSurfaceInfo* dsi_win; + * jboolean result; + * jint lock; + * + * // Get the AWT + * awt.version = JAWT_VERSION_1_3; + * result = JAWT_GetAWT(env, &awt); + * assert(result != JNI_FALSE); + * + * // Get the drawing surface + * ds = awt.GetDrawingSurface(env, canvas); + * assert(ds != NULL); + * + * // Lock the drawing surface + * lock = ds->Lock(ds); + * assert((lock & JAWT_LOCK_ERROR) == 0); + * + * // Get the drawing surface info + * dsi = ds->GetDrawingSurfaceInfo(ds); + * + * // Get the platform-specific drawing info + * dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; + * + * ////////////////////////////// + * // !!! DO PAINTING HERE !!! // + * ////////////////////////////// + * + * // Free the drawing surface info + * ds->FreeDrawingSurfaceInfo(dsi); + * + * // Unlock the drawing surface + * ds->Unlock(ds); + * + * // Free the drawing surface + * awt.FreeDrawingSurface(ds); + * } + * + */ + +/* + * JAWT_Rectangle + * Structure for a native rectangle. + */ +typedef struct jawt_Rectangle { + jint x; + jint y; + jint width; + jint height; +} JAWT_Rectangle; + +struct jawt_DrawingSurface; + +/* + * JAWT_DrawingSurfaceInfo + * Structure for containing the underlying drawing information of a component. + */ +typedef struct jawt_DrawingSurfaceInfo { + /* + * Pointer to the platform-specific information. This can be safely + * cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a + * JAWT_X11DrawingSurfaceInfo on Solaris. On Mac OS X this is a + * pointer to a NSObject that conforms to the JAWT_SurfaceLayers + * protocol. See jawt_md.h for details. + */ + void* platformInfo; + /* Cached pointer to the underlying drawing surface */ + struct jawt_DrawingSurface* ds; + /* Bounding rectangle of the drawing surface */ + JAWT_Rectangle bounds; + /* Number of rectangles in the clip */ + jint clipSize; + /* Clip rectangle array */ + JAWT_Rectangle* clip; +} JAWT_DrawingSurfaceInfo; + +#define JAWT_LOCK_ERROR 0x00000001 +#define JAWT_LOCK_CLIP_CHANGED 0x00000002 +#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004 +#define JAWT_LOCK_SURFACE_CHANGED 0x00000008 + +/* + * JAWT_DrawingSurface + * Structure for containing the underlying drawing information of a component. + * All operations on a JAWT_DrawingSurface MUST be performed from the same + * thread as the call to GetDrawingSurface. + */ +typedef struct jawt_DrawingSurface { + /* + * Cached reference to the Java environment of the calling thread. + * If Lock(), Unlock(), GetDrawingSurfaceInfo() or + * FreeDrawingSurfaceInfo() are called from a different thread, + * this data member should be set before calling those functions. + */ + JNIEnv* env; + /* Cached reference to the target object */ + jobject target; + /* + * Lock the surface of the target component for native rendering. + * When finished drawing, the surface must be unlocked with + * Unlock(). This function returns a bitmask with one or more of the + * following values: + * + * JAWT_LOCK_ERROR - When an error has occurred and the surface could not + * be locked. + * + * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed. + * + * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed. + * + * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed + */ + jint (JNICALL *Lock) + (struct jawt_DrawingSurface* ds); + /* + * Get the drawing surface info. + * The value returned may be cached, but the values may change if + * additional calls to Lock() or Unlock() are made. + * Lock() must be called before this can return a valid value. + * Returns NULL if an error has occurred. + * When finished with the returned value, FreeDrawingSurfaceInfo must be + * called. + */ + JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo) + (struct jawt_DrawingSurface* ds); + /* + * Free the drawing surface info. + */ + void (JNICALL *FreeDrawingSurfaceInfo) + (JAWT_DrawingSurfaceInfo* dsi); + /* + * Unlock the drawing surface of the target component for native rendering. + */ + void (JNICALL *Unlock) + (struct jawt_DrawingSurface* ds); +} JAWT_DrawingSurface; + +/* + * JAWT + * Structure for containing native AWT functions. + */ +typedef struct jawt { + /* + * Version of this structure. This must always be set before + * calling JAWT_GetAWT() + */ + jint version; + /* + * Return a drawing surface from a target jobject. This value + * may be cached. + * Returns NULL if an error has occurred. + * Target must be a java.awt.Component (should be a Canvas + * or Window for native rendering). + * FreeDrawingSurface() must be called when finished with the + * returned JAWT_DrawingSurface. + */ + JAWT_DrawingSurface* (JNICALL *GetDrawingSurface) + (JNIEnv* env, jobject target); + /* + * Free the drawing surface allocated in GetDrawingSurface. + */ + void (JNICALL *FreeDrawingSurface) + (JAWT_DrawingSurface* ds); + /* + * Since 1.4 + * Locks the entire AWT for synchronization purposes + */ + void (JNICALL *Lock)(JNIEnv* env); + /* + * Since 1.4 + * Unlocks the entire AWT for synchronization purposes + */ + void (JNICALL *Unlock)(JNIEnv* env); + /* + * Since 1.4 + * Returns a reference to a java.awt.Component from a native + * platform handle. On Windows, this corresponds to an HWND; + * on Solaris and Linux, this is a Drawable. For other platforms, + * see the appropriate machine-dependent header file for a description. + * The reference returned by this function is a local + * reference that is only valid in this environment. + * This function returns a NULL reference if no component could be + * found with matching platform information. + */ + jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo); + +} JAWT; + +/* + * Get the AWT native structure. This function returns JNI_FALSE if + * an error occurs. + */ +_JNI_IMPORT_OR_EXPORT_ +jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt); + +#define JAWT_VERSION_1_3 0x00010003 +#define JAWT_VERSION_1_4 0x00010004 +#define JAWT_VERSION_1_7 0x00010007 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* !_JAVASOFT_JAWT_H_ */ diff --git a/arthas-beans/src/main/native/head/jdwpTransport.h b/arthas-beans/src/main/native/head/jdwpTransport.h new file mode 100755 index 000000000..4f4b92ede --- /dev/null +++ b/arthas-beans/src/main/native/head/jdwpTransport.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * Java Debug Wire Protocol Transport Service Provider Interface. + */ + +#ifndef JDWPTRANSPORT_H +#define JDWPTRANSPORT_H + +#include "jni.h" + +enum { + JDWPTRANSPORT_VERSION_1_0 = 0x00010000 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +struct jdwpTransportNativeInterface_; + +struct _jdwpTransportEnv; + +#ifdef __cplusplus +typedef _jdwpTransportEnv jdwpTransportEnv; +#else +typedef const struct jdwpTransportNativeInterface_ *jdwpTransportEnv; +#endif /* __cplusplus */ + +/* + * Errors. Universal errors with JVMTI/JVMDI equivalents keep the + * values the same. + */ +typedef enum { + JDWPTRANSPORT_ERROR_NONE = 0, + JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT = 103, + JDWPTRANSPORT_ERROR_OUT_OF_MEMORY = 110, + JDWPTRANSPORT_ERROR_INTERNAL = 113, + JDWPTRANSPORT_ERROR_ILLEGAL_STATE = 201, + JDWPTRANSPORT_ERROR_IO_ERROR = 202, + JDWPTRANSPORT_ERROR_TIMEOUT = 203, + JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE = 204 +} jdwpTransportError; + + +/* + * Structure to define capabilities + */ +typedef struct { + unsigned int can_timeout_attach :1; + unsigned int can_timeout_accept :1; + unsigned int can_timeout_handshake :1; + unsigned int reserved3 :1; + unsigned int reserved4 :1; + unsigned int reserved5 :1; + unsigned int reserved6 :1; + unsigned int reserved7 :1; + unsigned int reserved8 :1; + unsigned int reserved9 :1; + unsigned int reserved10 :1; + unsigned int reserved11 :1; + unsigned int reserved12 :1; + unsigned int reserved13 :1; + unsigned int reserved14 :1; + unsigned int reserved15 :1; +} JDWPTransportCapabilities; + + +/* + * Structures to define packet layout. + * + * See: http://java.sun.com/j2se/1.5/docs/guide/jpda/jdwp-spec.html + */ + +enum { + /* + * If additional flags are added that apply to jdwpCmdPacket, + * then debugLoop.c: reader() will need to be updated to + * accept more than JDWPTRANSPORT_FLAGS_NONE. + */ + JDWPTRANSPORT_FLAGS_NONE = 0x0, + JDWPTRANSPORT_FLAGS_REPLY = 0x80 +}; + +typedef struct { + jint len; + jint id; + jbyte flags; + jbyte cmdSet; + jbyte cmd; + jbyte *data; +} jdwpCmdPacket; + +typedef struct { + jint len; + jint id; + jbyte flags; + jshort errorCode; + jbyte *data; +} jdwpReplyPacket; + +typedef struct { + union { + jdwpCmdPacket cmd; + jdwpReplyPacket reply; + } type; +} jdwpPacket; + +/* + * JDWP functions called by the transport. + */ +typedef struct jdwpTransportCallback { + void *(*alloc)(jint numBytes); /* Call this for all allocations */ + void (*free)(void *buffer); /* Call this for all deallocations */ +} jdwpTransportCallback; + +typedef jint (JNICALL *jdwpTransport_OnLoad_t)(JavaVM *jvm, + jdwpTransportCallback *callback, + jint version, + jdwpTransportEnv** env); + + + +/* Function Interface */ + +struct jdwpTransportNativeInterface_ { + /* 1 : RESERVED */ + void *reserved1; + + /* 2 : Get Capabilities */ + jdwpTransportError (JNICALL *GetCapabilities)(jdwpTransportEnv* env, + JDWPTransportCapabilities *capabilities_ptr); + + /* 3 : Attach */ + jdwpTransportError (JNICALL *Attach)(jdwpTransportEnv* env, + const char* address, + jlong attach_timeout, + jlong handshake_timeout); + + /* 4: StartListening */ + jdwpTransportError (JNICALL *StartListening)(jdwpTransportEnv* env, + const char* address, + char** actual_address); + + /* 5: StopListening */ + jdwpTransportError (JNICALL *StopListening)(jdwpTransportEnv* env); + + /* 6: Accept */ + jdwpTransportError (JNICALL *Accept)(jdwpTransportEnv* env, + jlong accept_timeout, + jlong handshake_timeout); + + /* 7: IsOpen */ + jboolean (JNICALL *IsOpen)(jdwpTransportEnv* env); + + /* 8: Close */ + jdwpTransportError (JNICALL *Close)(jdwpTransportEnv* env); + + /* 9: ReadPacket */ + jdwpTransportError (JNICALL *ReadPacket)(jdwpTransportEnv* env, + jdwpPacket *pkt); + + /* 10: Write Packet */ + jdwpTransportError (JNICALL *WritePacket)(jdwpTransportEnv* env, + const jdwpPacket* pkt); + + /* 11: GetLastError */ + jdwpTransportError (JNICALL *GetLastError)(jdwpTransportEnv* env, + char** error); + +}; + + +/* + * Use inlined functions so that C++ code can use syntax such as + * env->Attach("mymachine:5000", 10*1000, 0); + * + * rather than using C's :- + * + * (*env)->Attach(env, "mymachine:5000", 10*1000, 0); + */ +struct _jdwpTransportEnv { + const struct jdwpTransportNativeInterface_ *functions; +#ifdef __cplusplus + + jdwpTransportError GetCapabilities(JDWPTransportCapabilities *capabilities_ptr) { + return functions->GetCapabilities(this, capabilities_ptr); + } + + jdwpTransportError Attach(const char* address, jlong attach_timeout, + jlong handshake_timeout) { + return functions->Attach(this, address, attach_timeout, handshake_timeout); + } + + jdwpTransportError StartListening(const char* address, + char** actual_address) { + return functions->StartListening(this, address, actual_address); + } + + jdwpTransportError StopListening(void) { + return functions->StopListening(this); + } + + jdwpTransportError Accept(jlong accept_timeout, jlong handshake_timeout) { + return functions->Accept(this, accept_timeout, handshake_timeout); + } + + jboolean IsOpen(void) { + return functions->IsOpen(this); + } + + jdwpTransportError Close(void) { + return functions->Close(this); + } + + jdwpTransportError ReadPacket(jdwpPacket *pkt) { + return functions->ReadPacket(this, pkt); + } + + jdwpTransportError WritePacket(const jdwpPacket* pkt) { + return functions->WritePacket(this, pkt); + } + + jdwpTransportError GetLastError(char** error) { + return functions->GetLastError(this, error); + } + + +#endif /* __cplusplus */ +}; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* JDWPTRANSPORT_H */ diff --git a/arthas-beans/src/main/native/head/jni.h b/arthas-beans/src/main/native/head/jni.h new file mode 100755 index 000000000..0ffe244b6 --- /dev/null +++ b/arthas-beans/src/main/native/head/jni.h @@ -0,0 +1,1960 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * We used part of Netscape's Java Runtime Interface (JRI) as the starting + * point of our design and implementation. + */ + +/****************************************************************************** + * Java Runtime Interface + * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. + *****************************************************************************/ + +#ifndef _JAVASOFT_JNI_H_ +#define _JAVASOFT_JNI_H_ + +#include +#include + +/* jni_md.h contains the machine-dependent typedefs for jbyte, jint + and jlong */ + +#include "jni_md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * JNI Types + */ + +#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H + +typedef unsigned char jboolean; +typedef unsigned short jchar; +typedef short jshort; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +#ifdef __cplusplus + +class _jobject {}; +class _jclass : public _jobject {}; +class _jthrowable : public _jobject {}; +class _jstring : public _jobject {}; +class _jarray : public _jobject {}; +class _jbooleanArray : public _jarray {}; +class _jbyteArray : public _jarray {}; +class _jcharArray : public _jarray {}; +class _jshortArray : public _jarray {}; +class _jintArray : public _jarray {}; +class _jlongArray : public _jarray {}; +class _jfloatArray : public _jarray {}; +class _jdoubleArray : public _jarray {}; +class _jobjectArray : public _jarray {}; + +typedef _jobject *jobject; +typedef _jclass *jclass; +typedef _jthrowable *jthrowable; +typedef _jstring *jstring; +typedef _jarray *jarray; +typedef _jbooleanArray *jbooleanArray; +typedef _jbyteArray *jbyteArray; +typedef _jcharArray *jcharArray; +typedef _jshortArray *jshortArray; +typedef _jintArray *jintArray; +typedef _jlongArray *jlongArray; +typedef _jfloatArray *jfloatArray; +typedef _jdoubleArray *jdoubleArray; +typedef _jobjectArray *jobjectArray; + +#else + +struct _jobject; + +typedef struct _jobject *jobject; +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +#endif + +typedef jobject jweak; + +typedef union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +} jvalue; + +struct _jfieldID; +typedef struct _jfieldID *jfieldID; + +struct _jmethodID; +typedef struct _jmethodID *jmethodID; + +/* Return values from jobjectRefType */ +typedef enum _jobjectType { + JNIInvalidRefType = 0, + JNILocalRefType = 1, + JNIGlobalRefType = 2, + JNIWeakGlobalRefType = 3 +} jobjectRefType; + + +#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */ + +/* + * jboolean constants + */ + +#define JNI_FALSE 0 +#define JNI_TRUE 1 + +/* + * possible return values for JNI functions. + */ + +#define JNI_OK 0 /* success */ +#define JNI_ERR (-1) /* unknown error */ +#define JNI_EDETACHED (-2) /* thread detached from the VM */ +#define JNI_EVERSION (-3) /* JNI version error */ +#define JNI_ENOMEM (-4) /* not enough memory */ +#define JNI_EEXIST (-5) /* VM already created */ +#define JNI_EINVAL (-6) /* invalid arguments */ + +/* + * used in ReleaseScalarArrayElements + */ + +#define JNI_COMMIT 1 +#define JNI_ABORT 2 + +/* + * used in RegisterNatives to describe native method name, signature, + * and function pointer. + */ + +typedef struct { + char *name; + char *signature; + void *fnPtr; +} JNINativeMethod; + +/* + * JNI Native Method Interface. + */ + +struct JNINativeInterface_; + +struct JNIEnv_; + +#ifdef __cplusplus +typedef JNIEnv_ JNIEnv; +#else +typedef const struct JNINativeInterface_ *JNIEnv; +#endif + +/* + * JNI Invocation Interface. + */ + +struct JNIInvokeInterface_; + +struct JavaVM_; + +#ifdef __cplusplus +typedef JavaVM_ JavaVM; +#else +typedef const struct JNIInvokeInterface_ *JavaVM; +#endif + +struct JNINativeInterface_ { + void *reserved0; + void *reserved1; + void *reserved2; + + void *reserved3; + jint (JNICALL *GetVersion)(JNIEnv *env); + + jclass (JNICALL *DefineClass) + (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, + jsize len); + jclass (JNICALL *FindClass) + (JNIEnv *env, const char *name); + + jmethodID (JNICALL *FromReflectedMethod) + (JNIEnv *env, jobject method); + jfieldID (JNICALL *FromReflectedField) + (JNIEnv *env, jobject field); + + jobject (JNICALL *ToReflectedMethod) + (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic); + + jclass (JNICALL *GetSuperclass) + (JNIEnv *env, jclass sub); + jboolean (JNICALL *IsAssignableFrom) + (JNIEnv *env, jclass sub, jclass sup); + + jobject (JNICALL *ToReflectedField) + (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic); + + jint (JNICALL *Throw) + (JNIEnv *env, jthrowable obj); + jint (JNICALL *ThrowNew) + (JNIEnv *env, jclass clazz, const char *msg); + jthrowable (JNICALL *ExceptionOccurred) + (JNIEnv *env); + void (JNICALL *ExceptionDescribe) + (JNIEnv *env); + void (JNICALL *ExceptionClear) + (JNIEnv *env); + void (JNICALL *FatalError) + (JNIEnv *env, const char *msg); + + jint (JNICALL *PushLocalFrame) + (JNIEnv *env, jint capacity); + jobject (JNICALL *PopLocalFrame) + (JNIEnv *env, jobject result); + + jobject (JNICALL *NewGlobalRef) + (JNIEnv *env, jobject lobj); + void (JNICALL *DeleteGlobalRef) + (JNIEnv *env, jobject gref); + void (JNICALL *DeleteLocalRef) + (JNIEnv *env, jobject obj); + jboolean (JNICALL *IsSameObject) + (JNIEnv *env, jobject obj1, jobject obj2); + jobject (JNICALL *NewLocalRef) + (JNIEnv *env, jobject ref); + jint (JNICALL *EnsureLocalCapacity) + (JNIEnv *env, jint capacity); + + jobject (JNICALL *AllocObject) + (JNIEnv *env, jclass clazz); + jobject (JNICALL *NewObject) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *NewObjectV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *NewObjectA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jclass (JNICALL *GetObjectClass) + (JNIEnv *env, jobject obj); + jboolean (JNICALL *IsInstanceOf) + (JNIEnv *env, jobject obj, jclass clazz); + + jmethodID (JNICALL *GetMethodID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallObjectMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jobject (JNICALL *CallObjectMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jobject (JNICALL *CallObjectMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); + + jboolean (JNICALL *CallBooleanMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jboolean (JNICALL *CallBooleanMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jboolean (JNICALL *CallBooleanMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); + + jbyte (JNICALL *CallByteMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jbyte (JNICALL *CallByteMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jbyte (JNICALL *CallByteMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jchar (JNICALL *CallCharMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jchar (JNICALL *CallCharMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jchar (JNICALL *CallCharMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jshort (JNICALL *CallShortMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jshort (JNICALL *CallShortMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jshort (JNICALL *CallShortMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jint (JNICALL *CallIntMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jint (JNICALL *CallIntMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jint (JNICALL *CallIntMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jlong (JNICALL *CallLongMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jlong (JNICALL *CallLongMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jlong (JNICALL *CallLongMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jfloat (JNICALL *CallFloatMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jfloat (JNICALL *CallFloatMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jfloat (JNICALL *CallFloatMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jdouble (JNICALL *CallDoubleMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jdouble (JNICALL *CallDoubleMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jdouble (JNICALL *CallDoubleMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + void (JNICALL *CallVoidMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + void (JNICALL *CallVoidMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + void (JNICALL *CallVoidMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); + + jobject (JNICALL *CallNonvirtualObjectMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallNonvirtualObjectMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jobject (JNICALL *CallNonvirtualObjectMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue * args); + + jboolean (JNICALL *CallNonvirtualBooleanMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallNonvirtualBooleanMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jboolean (JNICALL *CallNonvirtualBooleanMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue * args); + + jbyte (JNICALL *CallNonvirtualByteMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallNonvirtualByteMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jbyte (JNICALL *CallNonvirtualByteMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jchar (JNICALL *CallNonvirtualCharMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallNonvirtualCharMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jchar (JNICALL *CallNonvirtualCharMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jshort (JNICALL *CallNonvirtualShortMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallNonvirtualShortMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jshort (JNICALL *CallNonvirtualShortMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jint (JNICALL *CallNonvirtualIntMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallNonvirtualIntMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jint (JNICALL *CallNonvirtualIntMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jlong (JNICALL *CallNonvirtualLongMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallNonvirtualLongMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jlong (JNICALL *CallNonvirtualLongMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jfloat (JNICALL *CallNonvirtualFloatMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallNonvirtualFloatMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jfloat (JNICALL *CallNonvirtualFloatMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jdouble (JNICALL *CallNonvirtualDoubleMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallNonvirtualDoubleMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jdouble (JNICALL *CallNonvirtualDoubleMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + void (JNICALL *CallNonvirtualVoidMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + void (JNICALL *CallNonvirtualVoidMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + void (JNICALL *CallNonvirtualVoidMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue * args); + + jfieldID (JNICALL *GetFieldID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *GetObjectField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jboolean (JNICALL *GetBooleanField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jbyte (JNICALL *GetByteField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jchar (JNICALL *GetCharField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jshort (JNICALL *GetShortField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jint (JNICALL *GetIntField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jlong (JNICALL *GetLongField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jfloat (JNICALL *GetFloatField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jdouble (JNICALL *GetDoubleField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + + void (JNICALL *SetObjectField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val); + void (JNICALL *SetBooleanField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val); + void (JNICALL *SetByteField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); + void (JNICALL *SetCharField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); + void (JNICALL *SetShortField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); + void (JNICALL *SetIntField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jint val); + void (JNICALL *SetLongField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); + void (JNICALL *SetFloatField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); + void (JNICALL *SetDoubleField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val); + + jmethodID (JNICALL *GetStaticMethodID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallStaticObjectMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallStaticObjectMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallStaticObjectMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jboolean (JNICALL *CallStaticBooleanMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallStaticBooleanMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallStaticBooleanMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jbyte (JNICALL *CallStaticByteMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallStaticByteMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallStaticByteMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jchar (JNICALL *CallStaticCharMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallStaticCharMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallStaticCharMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jshort (JNICALL *CallStaticShortMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallStaticShortMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallStaticShortMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jint (JNICALL *CallStaticIntMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallStaticIntMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallStaticIntMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jlong (JNICALL *CallStaticLongMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallStaticLongMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallStaticLongMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jfloat (JNICALL *CallStaticFloatMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallStaticFloatMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallStaticFloatMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jdouble (JNICALL *CallStaticDoubleMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallStaticDoubleMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallStaticDoubleMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + void (JNICALL *CallStaticVoidMethod) + (JNIEnv *env, jclass cls, jmethodID methodID, ...); + void (JNICALL *CallStaticVoidMethodV) + (JNIEnv *env, jclass cls, jmethodID methodID, va_list args); + void (JNICALL *CallStaticVoidMethodA) + (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args); + + jfieldID (JNICALL *GetStaticFieldID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + jobject (JNICALL *GetStaticObjectField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jboolean (JNICALL *GetStaticBooleanField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jbyte (JNICALL *GetStaticByteField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jchar (JNICALL *GetStaticCharField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jshort (JNICALL *GetStaticShortField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jint (JNICALL *GetStaticIntField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jlong (JNICALL *GetStaticLongField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jfloat (JNICALL *GetStaticFloatField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jdouble (JNICALL *GetStaticDoubleField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + + void (JNICALL *SetStaticObjectField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value); + void (JNICALL *SetStaticBooleanField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value); + void (JNICALL *SetStaticByteField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value); + void (JNICALL *SetStaticCharField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value); + void (JNICALL *SetStaticShortField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value); + void (JNICALL *SetStaticIntField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value); + void (JNICALL *SetStaticLongField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value); + void (JNICALL *SetStaticFloatField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value); + void (JNICALL *SetStaticDoubleField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value); + + jstring (JNICALL *NewString) + (JNIEnv *env, const jchar *unicode, jsize len); + jsize (JNICALL *GetStringLength) + (JNIEnv *env, jstring str); + const jchar *(JNICALL *GetStringChars) + (JNIEnv *env, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringChars) + (JNIEnv *env, jstring str, const jchar *chars); + + jstring (JNICALL *NewStringUTF) + (JNIEnv *env, const char *utf); + jsize (JNICALL *GetStringUTFLength) + (JNIEnv *env, jstring str); + const char* (JNICALL *GetStringUTFChars) + (JNIEnv *env, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringUTFChars) + (JNIEnv *env, jstring str, const char* chars); + + + jsize (JNICALL *GetArrayLength) + (JNIEnv *env, jarray array); + + jobjectArray (JNICALL *NewObjectArray) + (JNIEnv *env, jsize len, jclass clazz, jobject init); + jobject (JNICALL *GetObjectArrayElement) + (JNIEnv *env, jobjectArray array, jsize index); + void (JNICALL *SetObjectArrayElement) + (JNIEnv *env, jobjectArray array, jsize index, jobject val); + + jbooleanArray (JNICALL *NewBooleanArray) + (JNIEnv *env, jsize len); + jbyteArray (JNICALL *NewByteArray) + (JNIEnv *env, jsize len); + jcharArray (JNICALL *NewCharArray) + (JNIEnv *env, jsize len); + jshortArray (JNICALL *NewShortArray) + (JNIEnv *env, jsize len); + jintArray (JNICALL *NewIntArray) + (JNIEnv *env, jsize len); + jlongArray (JNICALL *NewLongArray) + (JNIEnv *env, jsize len); + jfloatArray (JNICALL *NewFloatArray) + (JNIEnv *env, jsize len); + jdoubleArray (JNICALL *NewDoubleArray) + (JNIEnv *env, jsize len); + + jboolean * (JNICALL *GetBooleanArrayElements) + (JNIEnv *env, jbooleanArray array, jboolean *isCopy); + jbyte * (JNICALL *GetByteArrayElements) + (JNIEnv *env, jbyteArray array, jboolean *isCopy); + jchar * (JNICALL *GetCharArrayElements) + (JNIEnv *env, jcharArray array, jboolean *isCopy); + jshort * (JNICALL *GetShortArrayElements) + (JNIEnv *env, jshortArray array, jboolean *isCopy); + jint * (JNICALL *GetIntArrayElements) + (JNIEnv *env, jintArray array, jboolean *isCopy); + jlong * (JNICALL *GetLongArrayElements) + (JNIEnv *env, jlongArray array, jboolean *isCopy); + jfloat * (JNICALL *GetFloatArrayElements) + (JNIEnv *env, jfloatArray array, jboolean *isCopy); + jdouble * (JNICALL *GetDoubleArrayElements) + (JNIEnv *env, jdoubleArray array, jboolean *isCopy); + + void (JNICALL *ReleaseBooleanArrayElements) + (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode); + void (JNICALL *ReleaseByteArrayElements) + (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode); + void (JNICALL *ReleaseCharArrayElements) + (JNIEnv *env, jcharArray array, jchar *elems, jint mode); + void (JNICALL *ReleaseShortArrayElements) + (JNIEnv *env, jshortArray array, jshort *elems, jint mode); + void (JNICALL *ReleaseIntArrayElements) + (JNIEnv *env, jintArray array, jint *elems, jint mode); + void (JNICALL *ReleaseLongArrayElements) + (JNIEnv *env, jlongArray array, jlong *elems, jint mode); + void (JNICALL *ReleaseFloatArrayElements) + (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode); + void (JNICALL *ReleaseDoubleArrayElements) + (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode); + + void (JNICALL *GetBooleanArrayRegion) + (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *GetByteArrayRegion) + (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *GetCharArrayRegion) + (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *GetShortArrayRegion) + (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *GetIntArrayRegion) + (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *GetLongArrayRegion) + (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *GetFloatArrayRegion) + (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *GetDoubleArrayRegion) + (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + void (JNICALL *SetBooleanArrayRegion) + (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf); + void (JNICALL *SetByteArrayRegion) + (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf); + void (JNICALL *SetCharArrayRegion) + (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf); + void (JNICALL *SetShortArrayRegion) + (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf); + void (JNICALL *SetIntArrayRegion) + (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf); + void (JNICALL *SetLongArrayRegion) + (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf); + void (JNICALL *SetFloatArrayRegion) + (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf); + void (JNICALL *SetDoubleArrayRegion) + (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf); + + jint (JNICALL *RegisterNatives) + (JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods); + jint (JNICALL *UnregisterNatives) + (JNIEnv *env, jclass clazz); + + jint (JNICALL *MonitorEnter) + (JNIEnv *env, jobject obj); + jint (JNICALL *MonitorExit) + (JNIEnv *env, jobject obj); + + jint (JNICALL *GetJavaVM) + (JNIEnv *env, JavaVM **vm); + + void (JNICALL *GetStringRegion) + (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf); + void (JNICALL *GetStringUTFRegion) + (JNIEnv *env, jstring str, jsize start, jsize len, char *buf); + + void * (JNICALL *GetPrimitiveArrayCritical) + (JNIEnv *env, jarray array, jboolean *isCopy); + void (JNICALL *ReleasePrimitiveArrayCritical) + (JNIEnv *env, jarray array, void *carray, jint mode); + + const jchar * (JNICALL *GetStringCritical) + (JNIEnv *env, jstring string, jboolean *isCopy); + void (JNICALL *ReleaseStringCritical) + (JNIEnv *env, jstring string, const jchar *cstring); + + jweak (JNICALL *NewWeakGlobalRef) + (JNIEnv *env, jobject obj); + void (JNICALL *DeleteWeakGlobalRef) + (JNIEnv *env, jweak ref); + + jboolean (JNICALL *ExceptionCheck) + (JNIEnv *env); + + jobject (JNICALL *NewDirectByteBuffer) + (JNIEnv* env, void* address, jlong capacity); + void* (JNICALL *GetDirectBufferAddress) + (JNIEnv* env, jobject buf); + jlong (JNICALL *GetDirectBufferCapacity) + (JNIEnv* env, jobject buf); + + /* New JNI 1.6 Features */ + + jobjectRefType (JNICALL *GetObjectRefType) + (JNIEnv* env, jobject obj); +}; + +/* + * We use inlined functions for C++ so that programmers can write: + * + * env->FindClass("java/lang/String") + * + * in C++ rather than: + * + * (*env)->FindClass(env, "java/lang/String") + * + * in C. + */ + +struct JNIEnv_ { + const struct JNINativeInterface_ *functions; +#ifdef __cplusplus + + jint GetVersion() { + return functions->GetVersion(this); + } + jclass DefineClass(const char *name, jobject loader, const jbyte *buf, + jsize len) { + return functions->DefineClass(this, name, loader, buf, len); + } + jclass FindClass(const char *name) { + return functions->FindClass(this, name); + } + jmethodID FromReflectedMethod(jobject method) { + return functions->FromReflectedMethod(this,method); + } + jfieldID FromReflectedField(jobject field) { + return functions->FromReflectedField(this,field); + } + + jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) { + return functions->ToReflectedMethod(this, cls, methodID, isStatic); + } + + jclass GetSuperclass(jclass sub) { + return functions->GetSuperclass(this, sub); + } + jboolean IsAssignableFrom(jclass sub, jclass sup) { + return functions->IsAssignableFrom(this, sub, sup); + } + + jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) { + return functions->ToReflectedField(this,cls,fieldID,isStatic); + } + + jint Throw(jthrowable obj) { + return functions->Throw(this, obj); + } + jint ThrowNew(jclass clazz, const char *msg) { + return functions->ThrowNew(this, clazz, msg); + } + jthrowable ExceptionOccurred() { + return functions->ExceptionOccurred(this); + } + void ExceptionDescribe() { + functions->ExceptionDescribe(this); + } + void ExceptionClear() { + functions->ExceptionClear(this); + } + void FatalError(const char *msg) { + functions->FatalError(this, msg); + } + + jint PushLocalFrame(jint capacity) { + return functions->PushLocalFrame(this,capacity); + } + jobject PopLocalFrame(jobject result) { + return functions->PopLocalFrame(this,result); + } + + jobject NewGlobalRef(jobject lobj) { + return functions->NewGlobalRef(this,lobj); + } + void DeleteGlobalRef(jobject gref) { + functions->DeleteGlobalRef(this,gref); + } + void DeleteLocalRef(jobject obj) { + functions->DeleteLocalRef(this, obj); + } + + jboolean IsSameObject(jobject obj1, jobject obj2) { + return functions->IsSameObject(this,obj1,obj2); + } + + jobject NewLocalRef(jobject ref) { + return functions->NewLocalRef(this,ref); + } + jint EnsureLocalCapacity(jint capacity) { + return functions->EnsureLocalCapacity(this,capacity); + } + + jobject AllocObject(jclass clazz) { + return functions->AllocObject(this,clazz); + } + jobject NewObject(jclass clazz, jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args, methodID); + result = functions->NewObjectV(this,clazz,methodID,args); + va_end(args); + return result; + } + jobject NewObjectV(jclass clazz, jmethodID methodID, + va_list args) { + return functions->NewObjectV(this,clazz,methodID,args); + } + jobject NewObjectA(jclass clazz, jmethodID methodID, + const jvalue *args) { + return functions->NewObjectA(this,clazz,methodID,args); + } + + jclass GetObjectClass(jobject obj) { + return functions->GetObjectClass(this,obj); + } + jboolean IsInstanceOf(jobject obj, jclass clazz) { + return functions->IsInstanceOf(this,obj,clazz); + } + + jmethodID GetMethodID(jclass clazz, const char *name, + const char *sig) { + return functions->GetMethodID(this,clazz,name,sig); + } + + jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallObjectMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jobject CallObjectMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallObjectMethodV(this,obj,methodID,args); + } + jobject CallObjectMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallObjectMethodA(this,obj,methodID,args); + } + + jboolean CallBooleanMethod(jobject obj, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallBooleanMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jboolean CallBooleanMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallBooleanMethodV(this,obj,methodID,args); + } + jboolean CallBooleanMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallBooleanMethodA(this,obj,methodID, args); + } + + jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallByteMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jbyte CallByteMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallByteMethodV(this,obj,methodID,args); + } + jbyte CallByteMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallByteMethodA(this,obj,methodID,args); + } + + jchar CallCharMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallCharMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jchar CallCharMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallCharMethodV(this,obj,methodID,args); + } + jchar CallCharMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallCharMethodA(this,obj,methodID,args); + } + + jshort CallShortMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallShortMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jshort CallShortMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallShortMethodV(this,obj,methodID,args); + } + jshort CallShortMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallShortMethodA(this,obj,methodID,args); + } + + jint CallIntMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallIntMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jint CallIntMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallIntMethodV(this,obj,methodID,args); + } + jint CallIntMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallIntMethodA(this,obj,methodID,args); + } + + jlong CallLongMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallLongMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jlong CallLongMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallLongMethodV(this,obj,methodID,args); + } + jlong CallLongMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallLongMethodA(this,obj,methodID,args); + } + + jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallFloatMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jfloat CallFloatMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallFloatMethodV(this,obj,methodID,args); + } + jfloat CallFloatMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallFloatMethodA(this,obj,methodID,args); + } + + jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallDoubleMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jdouble CallDoubleMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallDoubleMethodV(this,obj,methodID,args); + } + jdouble CallDoubleMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallDoubleMethodA(this,obj,methodID,args); + } + + void CallVoidMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallVoidMethodV(this,obj,methodID,args); + va_end(args); + } + void CallVoidMethodV(jobject obj, jmethodID methodID, + va_list args) { + functions->CallVoidMethodV(this,obj,methodID,args); + } + void CallVoidMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + functions->CallVoidMethodA(this,obj,methodID,args); + } + + jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallNonvirtualObjectMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualObjectMethodV(this,obj,clazz, + methodID,args); + } + jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualObjectMethodA(this,obj,clazz, + methodID,args); + } + + jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualBooleanMethodV(this,obj,clazz, + methodID,args); + } + jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualBooleanMethodA(this,obj,clazz, + methodID, args); + } + + jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallNonvirtualByteMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualByteMethodV(this,obj,clazz, + methodID,args); + } + jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualByteMethodA(this,obj,clazz, + methodID,args); + } + + jchar CallNonvirtualCharMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallNonvirtualCharMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualCharMethodV(this,obj,clazz, + methodID,args); + } + jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualCharMethodA(this,obj,clazz, + methodID,args); + } + + jshort CallNonvirtualShortMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallNonvirtualShortMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualShortMethodV(this,obj,clazz, + methodID,args); + } + jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualShortMethodA(this,obj,clazz, + methodID,args); + } + + jint CallNonvirtualIntMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallNonvirtualIntMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jint CallNonvirtualIntMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualIntMethodV(this,obj,clazz, + methodID,args); + } + jint CallNonvirtualIntMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualIntMethodA(this,obj,clazz, + methodID,args); + } + + jlong CallNonvirtualLongMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallNonvirtualLongMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualLongMethodV(this,obj,clazz, + methodID,args); + } + jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualLongMethodA(this,obj,clazz, + methodID,args); + } + + jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallNonvirtualFloatMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + return functions->CallNonvirtualFloatMethodV(this,obj,clazz, + methodID,args); + } + jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz, + jmethodID methodID, + const jvalue * args) { + return functions->CallNonvirtualFloatMethodA(this,obj,clazz, + methodID,args); + } + + jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + return functions->CallNonvirtualDoubleMethodV(this,obj,clazz, + methodID,args); + } + jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, + jmethodID methodID, + const jvalue * args) { + return functions->CallNonvirtualDoubleMethodA(this,obj,clazz, + methodID,args); + } + + void CallNonvirtualVoidMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); + va_end(args); + } + void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); + } + void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, + jmethodID methodID, + const jvalue * args) { + functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args); + } + + jfieldID GetFieldID(jclass clazz, const char *name, + const char *sig) { + return functions->GetFieldID(this,clazz,name,sig); + } + + jobject GetObjectField(jobject obj, jfieldID fieldID) { + return functions->GetObjectField(this,obj,fieldID); + } + jboolean GetBooleanField(jobject obj, jfieldID fieldID) { + return functions->GetBooleanField(this,obj,fieldID); + } + jbyte GetByteField(jobject obj, jfieldID fieldID) { + return functions->GetByteField(this,obj,fieldID); + } + jchar GetCharField(jobject obj, jfieldID fieldID) { + return functions->GetCharField(this,obj,fieldID); + } + jshort GetShortField(jobject obj, jfieldID fieldID) { + return functions->GetShortField(this,obj,fieldID); + } + jint GetIntField(jobject obj, jfieldID fieldID) { + return functions->GetIntField(this,obj,fieldID); + } + jlong GetLongField(jobject obj, jfieldID fieldID) { + return functions->GetLongField(this,obj,fieldID); + } + jfloat GetFloatField(jobject obj, jfieldID fieldID) { + return functions->GetFloatField(this,obj,fieldID); + } + jdouble GetDoubleField(jobject obj, jfieldID fieldID) { + return functions->GetDoubleField(this,obj,fieldID); + } + + void SetObjectField(jobject obj, jfieldID fieldID, jobject val) { + functions->SetObjectField(this,obj,fieldID,val); + } + void SetBooleanField(jobject obj, jfieldID fieldID, + jboolean val) { + functions->SetBooleanField(this,obj,fieldID,val); + } + void SetByteField(jobject obj, jfieldID fieldID, + jbyte val) { + functions->SetByteField(this,obj,fieldID,val); + } + void SetCharField(jobject obj, jfieldID fieldID, + jchar val) { + functions->SetCharField(this,obj,fieldID,val); + } + void SetShortField(jobject obj, jfieldID fieldID, + jshort val) { + functions->SetShortField(this,obj,fieldID,val); + } + void SetIntField(jobject obj, jfieldID fieldID, + jint val) { + functions->SetIntField(this,obj,fieldID,val); + } + void SetLongField(jobject obj, jfieldID fieldID, + jlong val) { + functions->SetLongField(this,obj,fieldID,val); + } + void SetFloatField(jobject obj, jfieldID fieldID, + jfloat val) { + functions->SetFloatField(this,obj,fieldID,val); + } + void SetDoubleField(jobject obj, jfieldID fieldID, + jdouble val) { + functions->SetDoubleField(this,obj,fieldID,val); + } + + jmethodID GetStaticMethodID(jclass clazz, const char *name, + const char *sig) { + return functions->GetStaticMethodID(this,clazz,name,sig); + } + + jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID, + ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallStaticObjectMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID, + va_list args) { + return functions->CallStaticObjectMethodV(this,clazz,methodID,args); + } + jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID, + const jvalue *args) { + return functions->CallStaticObjectMethodA(this,clazz,methodID,args); + } + + jboolean CallStaticBooleanMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jboolean CallStaticBooleanMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticBooleanMethodV(this,clazz,methodID,args); + } + jboolean CallStaticBooleanMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticBooleanMethodA(this,clazz,methodID,args); + } + + jbyte CallStaticByteMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallStaticByteMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jbyte CallStaticByteMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticByteMethodV(this,clazz,methodID,args); + } + jbyte CallStaticByteMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticByteMethodA(this,clazz,methodID,args); + } + + jchar CallStaticCharMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallStaticCharMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jchar CallStaticCharMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticCharMethodV(this,clazz,methodID,args); + } + jchar CallStaticCharMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticCharMethodA(this,clazz,methodID,args); + } + + jshort CallStaticShortMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallStaticShortMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jshort CallStaticShortMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticShortMethodV(this,clazz,methodID,args); + } + jshort CallStaticShortMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticShortMethodA(this,clazz,methodID,args); + } + + jint CallStaticIntMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallStaticIntMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jint CallStaticIntMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticIntMethodV(this,clazz,methodID,args); + } + jint CallStaticIntMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticIntMethodA(this,clazz,methodID,args); + } + + jlong CallStaticLongMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallStaticLongMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jlong CallStaticLongMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticLongMethodV(this,clazz,methodID,args); + } + jlong CallStaticLongMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticLongMethodA(this,clazz,methodID,args); + } + + jfloat CallStaticFloatMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallStaticFloatMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jfloat CallStaticFloatMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticFloatMethodV(this,clazz,methodID,args); + } + jfloat CallStaticFloatMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticFloatMethodA(this,clazz,methodID,args); + } + + jdouble CallStaticDoubleMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jdouble CallStaticDoubleMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticDoubleMethodV(this,clazz,methodID,args); + } + jdouble CallStaticDoubleMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticDoubleMethodA(this,clazz,methodID,args); + } + + void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallStaticVoidMethodV(this,cls,methodID,args); + va_end(args); + } + void CallStaticVoidMethodV(jclass cls, jmethodID methodID, + va_list args) { + functions->CallStaticVoidMethodV(this,cls,methodID,args); + } + void CallStaticVoidMethodA(jclass cls, jmethodID methodID, + const jvalue * args) { + functions->CallStaticVoidMethodA(this,cls,methodID,args); + } + + jfieldID GetStaticFieldID(jclass clazz, const char *name, + const char *sig) { + return functions->GetStaticFieldID(this,clazz,name,sig); + } + jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticObjectField(this,clazz,fieldID); + } + jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticBooleanField(this,clazz,fieldID); + } + jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticByteField(this,clazz,fieldID); + } + jchar GetStaticCharField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticCharField(this,clazz,fieldID); + } + jshort GetStaticShortField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticShortField(this,clazz,fieldID); + } + jint GetStaticIntField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticIntField(this,clazz,fieldID); + } + jlong GetStaticLongField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticLongField(this,clazz,fieldID); + } + jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticFloatField(this,clazz,fieldID); + } + jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticDoubleField(this,clazz,fieldID); + } + + void SetStaticObjectField(jclass clazz, jfieldID fieldID, + jobject value) { + functions->SetStaticObjectField(this,clazz,fieldID,value); + } + void SetStaticBooleanField(jclass clazz, jfieldID fieldID, + jboolean value) { + functions->SetStaticBooleanField(this,clazz,fieldID,value); + } + void SetStaticByteField(jclass clazz, jfieldID fieldID, + jbyte value) { + functions->SetStaticByteField(this,clazz,fieldID,value); + } + void SetStaticCharField(jclass clazz, jfieldID fieldID, + jchar value) { + functions->SetStaticCharField(this,clazz,fieldID,value); + } + void SetStaticShortField(jclass clazz, jfieldID fieldID, + jshort value) { + functions->SetStaticShortField(this,clazz,fieldID,value); + } + void SetStaticIntField(jclass clazz, jfieldID fieldID, + jint value) { + functions->SetStaticIntField(this,clazz,fieldID,value); + } + void SetStaticLongField(jclass clazz, jfieldID fieldID, + jlong value) { + functions->SetStaticLongField(this,clazz,fieldID,value); + } + void SetStaticFloatField(jclass clazz, jfieldID fieldID, + jfloat value) { + functions->SetStaticFloatField(this,clazz,fieldID,value); + } + void SetStaticDoubleField(jclass clazz, jfieldID fieldID, + jdouble value) { + functions->SetStaticDoubleField(this,clazz,fieldID,value); + } + + jstring NewString(const jchar *unicode, jsize len) { + return functions->NewString(this,unicode,len); + } + jsize GetStringLength(jstring str) { + return functions->GetStringLength(this,str); + } + const jchar *GetStringChars(jstring str, jboolean *isCopy) { + return functions->GetStringChars(this,str,isCopy); + } + void ReleaseStringChars(jstring str, const jchar *chars) { + functions->ReleaseStringChars(this,str,chars); + } + + jstring NewStringUTF(const char *utf) { + return functions->NewStringUTF(this,utf); + } + jsize GetStringUTFLength(jstring str) { + return functions->GetStringUTFLength(this,str); + } + const char* GetStringUTFChars(jstring str, jboolean *isCopy) { + return functions->GetStringUTFChars(this,str,isCopy); + } + void ReleaseStringUTFChars(jstring str, const char* chars) { + functions->ReleaseStringUTFChars(this,str,chars); + } + + jsize GetArrayLength(jarray array) { + return functions->GetArrayLength(this,array); + } + + jobjectArray NewObjectArray(jsize len, jclass clazz, + jobject init) { + return functions->NewObjectArray(this,len,clazz,init); + } + jobject GetObjectArrayElement(jobjectArray array, jsize index) { + return functions->GetObjectArrayElement(this,array,index); + } + void SetObjectArrayElement(jobjectArray array, jsize index, + jobject val) { + functions->SetObjectArrayElement(this,array,index,val); + } + + jbooleanArray NewBooleanArray(jsize len) { + return functions->NewBooleanArray(this,len); + } + jbyteArray NewByteArray(jsize len) { + return functions->NewByteArray(this,len); + } + jcharArray NewCharArray(jsize len) { + return functions->NewCharArray(this,len); + } + jshortArray NewShortArray(jsize len) { + return functions->NewShortArray(this,len); + } + jintArray NewIntArray(jsize len) { + return functions->NewIntArray(this,len); + } + jlongArray NewLongArray(jsize len) { + return functions->NewLongArray(this,len); + } + jfloatArray NewFloatArray(jsize len) { + return functions->NewFloatArray(this,len); + } + jdoubleArray NewDoubleArray(jsize len) { + return functions->NewDoubleArray(this,len); + } + + jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) { + return functions->GetBooleanArrayElements(this,array,isCopy); + } + jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) { + return functions->GetByteArrayElements(this,array,isCopy); + } + jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) { + return functions->GetCharArrayElements(this,array,isCopy); + } + jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) { + return functions->GetShortArrayElements(this,array,isCopy); + } + jint * GetIntArrayElements(jintArray array, jboolean *isCopy) { + return functions->GetIntArrayElements(this,array,isCopy); + } + jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) { + return functions->GetLongArrayElements(this,array,isCopy); + } + jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) { + return functions->GetFloatArrayElements(this,array,isCopy); + } + jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) { + return functions->GetDoubleArrayElements(this,array,isCopy); + } + + void ReleaseBooleanArrayElements(jbooleanArray array, + jboolean *elems, + jint mode) { + functions->ReleaseBooleanArrayElements(this,array,elems,mode); + } + void ReleaseByteArrayElements(jbyteArray array, + jbyte *elems, + jint mode) { + functions->ReleaseByteArrayElements(this,array,elems,mode); + } + void ReleaseCharArrayElements(jcharArray array, + jchar *elems, + jint mode) { + functions->ReleaseCharArrayElements(this,array,elems,mode); + } + void ReleaseShortArrayElements(jshortArray array, + jshort *elems, + jint mode) { + functions->ReleaseShortArrayElements(this,array,elems,mode); + } + void ReleaseIntArrayElements(jintArray array, + jint *elems, + jint mode) { + functions->ReleaseIntArrayElements(this,array,elems,mode); + } + void ReleaseLongArrayElements(jlongArray array, + jlong *elems, + jint mode) { + functions->ReleaseLongArrayElements(this,array,elems,mode); + } + void ReleaseFloatArrayElements(jfloatArray array, + jfloat *elems, + jint mode) { + functions->ReleaseFloatArrayElements(this,array,elems,mode); + } + void ReleaseDoubleArrayElements(jdoubleArray array, + jdouble *elems, + jint mode) { + functions->ReleaseDoubleArrayElements(this,array,elems,mode); + } + + void GetBooleanArrayRegion(jbooleanArray array, + jsize start, jsize len, jboolean *buf) { + functions->GetBooleanArrayRegion(this,array,start,len,buf); + } + void GetByteArrayRegion(jbyteArray array, + jsize start, jsize len, jbyte *buf) { + functions->GetByteArrayRegion(this,array,start,len,buf); + } + void GetCharArrayRegion(jcharArray array, + jsize start, jsize len, jchar *buf) { + functions->GetCharArrayRegion(this,array,start,len,buf); + } + void GetShortArrayRegion(jshortArray array, + jsize start, jsize len, jshort *buf) { + functions->GetShortArrayRegion(this,array,start,len,buf); + } + void GetIntArrayRegion(jintArray array, + jsize start, jsize len, jint *buf) { + functions->GetIntArrayRegion(this,array,start,len,buf); + } + void GetLongArrayRegion(jlongArray array, + jsize start, jsize len, jlong *buf) { + functions->GetLongArrayRegion(this,array,start,len,buf); + } + void GetFloatArrayRegion(jfloatArray array, + jsize start, jsize len, jfloat *buf) { + functions->GetFloatArrayRegion(this,array,start,len,buf); + } + void GetDoubleArrayRegion(jdoubleArray array, + jsize start, jsize len, jdouble *buf) { + functions->GetDoubleArrayRegion(this,array,start,len,buf); + } + + void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, + const jboolean *buf) { + functions->SetBooleanArrayRegion(this,array,start,len,buf); + } + void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, + const jbyte *buf) { + functions->SetByteArrayRegion(this,array,start,len,buf); + } + void SetCharArrayRegion(jcharArray array, jsize start, jsize len, + const jchar *buf) { + functions->SetCharArrayRegion(this,array,start,len,buf); + } + void SetShortArrayRegion(jshortArray array, jsize start, jsize len, + const jshort *buf) { + functions->SetShortArrayRegion(this,array,start,len,buf); + } + void SetIntArrayRegion(jintArray array, jsize start, jsize len, + const jint *buf) { + functions->SetIntArrayRegion(this,array,start,len,buf); + } + void SetLongArrayRegion(jlongArray array, jsize start, jsize len, + const jlong *buf) { + functions->SetLongArrayRegion(this,array,start,len,buf); + } + void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, + const jfloat *buf) { + functions->SetFloatArrayRegion(this,array,start,len,buf); + } + void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, + const jdouble *buf) { + functions->SetDoubleArrayRegion(this,array,start,len,buf); + } + + jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, + jint nMethods) { + return functions->RegisterNatives(this,clazz,methods,nMethods); + } + jint UnregisterNatives(jclass clazz) { + return functions->UnregisterNatives(this,clazz); + } + + jint MonitorEnter(jobject obj) { + return functions->MonitorEnter(this,obj); + } + jint MonitorExit(jobject obj) { + return functions->MonitorExit(this,obj); + } + + jint GetJavaVM(JavaVM **vm) { + return functions->GetJavaVM(this,vm); + } + + void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) { + functions->GetStringRegion(this,str,start,len,buf); + } + void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) { + functions->GetStringUTFRegion(this,str,start,len,buf); + } + + void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) { + return functions->GetPrimitiveArrayCritical(this,array,isCopy); + } + void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) { + functions->ReleasePrimitiveArrayCritical(this,array,carray,mode); + } + + const jchar * GetStringCritical(jstring string, jboolean *isCopy) { + return functions->GetStringCritical(this,string,isCopy); + } + void ReleaseStringCritical(jstring string, const jchar *cstring) { + functions->ReleaseStringCritical(this,string,cstring); + } + + jweak NewWeakGlobalRef(jobject obj) { + return functions->NewWeakGlobalRef(this,obj); + } + void DeleteWeakGlobalRef(jweak ref) { + functions->DeleteWeakGlobalRef(this,ref); + } + + jboolean ExceptionCheck() { + return functions->ExceptionCheck(this); + } + + jobject NewDirectByteBuffer(void* address, jlong capacity) { + return functions->NewDirectByteBuffer(this, address, capacity); + } + void* GetDirectBufferAddress(jobject buf) { + return functions->GetDirectBufferAddress(this, buf); + } + jlong GetDirectBufferCapacity(jobject buf) { + return functions->GetDirectBufferCapacity(this, buf); + } + jobjectRefType GetObjectRefType(jobject obj) { + return functions->GetObjectRefType(this, obj); + } + +#endif /* __cplusplus */ +}; + +typedef struct JavaVMOption { + char *optionString; + void *extraInfo; +} JavaVMOption; + +typedef struct JavaVMInitArgs { + jint version; + + jint nOptions; + JavaVMOption *options; + jboolean ignoreUnrecognized; +} JavaVMInitArgs; + +typedef struct JavaVMAttachArgs { + jint version; + + char *name; + jobject group; +} JavaVMAttachArgs; + +/* These will be VM-specific. */ + +#define JDK1_2 +#define JDK1_4 + +/* End VM-specific. */ + +struct JNIInvokeInterface_ { + void *reserved0; + void *reserved1; + void *reserved2; + + jint (JNICALL *DestroyJavaVM)(JavaVM *vm); + + jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args); + + jint (JNICALL *DetachCurrentThread)(JavaVM *vm); + + jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version); + + jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args); +}; + +struct JavaVM_ { + const struct JNIInvokeInterface_ *functions; +#ifdef __cplusplus + + jint DestroyJavaVM() { + return functions->DestroyJavaVM(this); + } + jint AttachCurrentThread(void **penv, void *args) { + return functions->AttachCurrentThread(this, penv, args); + } + jint DetachCurrentThread() { + return functions->DetachCurrentThread(this); + } + + jint GetEnv(void **penv, jint version) { + return functions->GetEnv(this, penv, version); + } + jint AttachCurrentThreadAsDaemon(void **penv, void *args) { + return functions->AttachCurrentThreadAsDaemon(this, penv, args); + } +#endif +}; + +#ifdef _JNI_IMPLEMENTATION_ +#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT +#else +#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT +#endif +_JNI_IMPORT_OR_EXPORT_ jint JNICALL +JNI_GetDefaultJavaVMInitArgs(void *args); + +_JNI_IMPORT_OR_EXPORT_ jint JNICALL +JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args); + +_JNI_IMPORT_OR_EXPORT_ jint JNICALL +JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *); + +/* Defined by native libraries. */ +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *reserved); + +JNIEXPORT void JNICALL +JNI_OnUnload(JavaVM *vm, void *reserved); + +#define JNI_VERSION_1_1 0x00010001 +#define JNI_VERSION_1_2 0x00010002 +#define JNI_VERSION_1_4 0x00010004 +#define JNI_VERSION_1_6 0x00010006 +#define JNI_VERSION_1_8 0x00010008 + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* !_JAVASOFT_JNI_H_ */ diff --git a/arthas-beans/src/main/native/head/jvmti.h b/arthas-beans/src/main/native/head/jvmti.h new file mode 100755 index 000000000..74243f540 --- /dev/null +++ b/arthas-beans/src/main/native/head/jvmti.h @@ -0,0 +1,2534 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + + /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ + + + /* Include file for the Java(tm) Virtual Machine Tool Interface */ + +#ifndef _JAVA_JVMTI_H_ +#define _JAVA_JVMTI_H_ + +#include "jni.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + JVMTI_VERSION_1 = 0x30010000, + JVMTI_VERSION_1_0 = 0x30010000, + JVMTI_VERSION_1_1 = 0x30010100, + JVMTI_VERSION_1_2 = 0x30010200, + + JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */ +}; + +JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *vm, char *options, void *reserved); + +JNIEXPORT jint JNICALL +Agent_OnAttach(JavaVM* vm, char* options, void* reserved); + +JNIEXPORT void JNICALL +Agent_OnUnload(JavaVM *vm); + + /* Forward declaration of the environment */ + +struct _jvmtiEnv; + +struct jvmtiInterface_1_; + +#ifdef __cplusplus +typedef _jvmtiEnv jvmtiEnv; +#else +typedef const struct jvmtiInterface_1_ *jvmtiEnv; +#endif /* __cplusplus */ + +/* Derived Base Types */ + +typedef jobject jthread; +typedef jobject jthreadGroup; +typedef jlong jlocation; +struct _jrawMonitorID; +typedef struct _jrawMonitorID *jrawMonitorID; +typedef struct JNINativeInterface_ jniNativeInterface; + + /* Constants */ + + + /* Thread State Flags */ + +enum { + JVMTI_THREAD_STATE_ALIVE = 0x0001, + JVMTI_THREAD_STATE_TERMINATED = 0x0002, + JVMTI_THREAD_STATE_RUNNABLE = 0x0004, + JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400, + JVMTI_THREAD_STATE_WAITING = 0x0080, + JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010, + JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020, + JVMTI_THREAD_STATE_SLEEPING = 0x0040, + JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100, + JVMTI_THREAD_STATE_PARKED = 0x0200, + JVMTI_THREAD_STATE_SUSPENDED = 0x100000, + JVMTI_THREAD_STATE_INTERRUPTED = 0x200000, + JVMTI_THREAD_STATE_IN_NATIVE = 0x400000, + JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000, + JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000, + JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000 +}; + + /* java.lang.Thread.State Conversion Masks */ + +enum { + JVMTI_JAVA_LANG_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT, + JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0, + JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED, + JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE, + JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER, + JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY, + JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +}; + + /* Thread Priority Constants */ + +enum { + JVMTI_THREAD_MIN_PRIORITY = 1, + JVMTI_THREAD_NORM_PRIORITY = 5, + JVMTI_THREAD_MAX_PRIORITY = 10 +}; + + /* Heap Filter Flags */ + +enum { + JVMTI_HEAP_FILTER_TAGGED = 0x4, + JVMTI_HEAP_FILTER_UNTAGGED = 0x8, + JVMTI_HEAP_FILTER_CLASS_TAGGED = 0x10, + JVMTI_HEAP_FILTER_CLASS_UNTAGGED = 0x20 +}; + + /* Heap Visit Control Flags */ + +enum { + JVMTI_VISIT_OBJECTS = 0x100, + JVMTI_VISIT_ABORT = 0x8000 +}; + + /* Heap Reference Enumeration */ + +typedef enum { + JVMTI_HEAP_REFERENCE_CLASS = 1, + JVMTI_HEAP_REFERENCE_FIELD = 2, + JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT = 3, + JVMTI_HEAP_REFERENCE_CLASS_LOADER = 4, + JVMTI_HEAP_REFERENCE_SIGNERS = 5, + JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN = 6, + JVMTI_HEAP_REFERENCE_INTERFACE = 7, + JVMTI_HEAP_REFERENCE_STATIC_FIELD = 8, + JVMTI_HEAP_REFERENCE_CONSTANT_POOL = 9, + JVMTI_HEAP_REFERENCE_SUPERCLASS = 10, + JVMTI_HEAP_REFERENCE_JNI_GLOBAL = 21, + JVMTI_HEAP_REFERENCE_SYSTEM_CLASS = 22, + JVMTI_HEAP_REFERENCE_MONITOR = 23, + JVMTI_HEAP_REFERENCE_STACK_LOCAL = 24, + JVMTI_HEAP_REFERENCE_JNI_LOCAL = 25, + JVMTI_HEAP_REFERENCE_THREAD = 26, + JVMTI_HEAP_REFERENCE_OTHER = 27 +} jvmtiHeapReferenceKind; + + /* Primitive Type Enumeration */ + +typedef enum { + JVMTI_PRIMITIVE_TYPE_BOOLEAN = 90, + JVMTI_PRIMITIVE_TYPE_BYTE = 66, + JVMTI_PRIMITIVE_TYPE_CHAR = 67, + JVMTI_PRIMITIVE_TYPE_SHORT = 83, + JVMTI_PRIMITIVE_TYPE_INT = 73, + JVMTI_PRIMITIVE_TYPE_LONG = 74, + JVMTI_PRIMITIVE_TYPE_FLOAT = 70, + JVMTI_PRIMITIVE_TYPE_DOUBLE = 68 +} jvmtiPrimitiveType; + + /* Heap Object Filter Enumeration */ + +typedef enum { + JVMTI_HEAP_OBJECT_TAGGED = 1, + JVMTI_HEAP_OBJECT_UNTAGGED = 2, + JVMTI_HEAP_OBJECT_EITHER = 3 +} jvmtiHeapObjectFilter; + + /* Heap Root Kind Enumeration */ + +typedef enum { + JVMTI_HEAP_ROOT_JNI_GLOBAL = 1, + JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2, + JVMTI_HEAP_ROOT_MONITOR = 3, + JVMTI_HEAP_ROOT_STACK_LOCAL = 4, + JVMTI_HEAP_ROOT_JNI_LOCAL = 5, + JVMTI_HEAP_ROOT_THREAD = 6, + JVMTI_HEAP_ROOT_OTHER = 7 +} jvmtiHeapRootKind; + + /* Object Reference Enumeration */ + +typedef enum { + JVMTI_REFERENCE_CLASS = 1, + JVMTI_REFERENCE_FIELD = 2, + JVMTI_REFERENCE_ARRAY_ELEMENT = 3, + JVMTI_REFERENCE_CLASS_LOADER = 4, + JVMTI_REFERENCE_SIGNERS = 5, + JVMTI_REFERENCE_PROTECTION_DOMAIN = 6, + JVMTI_REFERENCE_INTERFACE = 7, + JVMTI_REFERENCE_STATIC_FIELD = 8, + JVMTI_REFERENCE_CONSTANT_POOL = 9 +} jvmtiObjectReferenceKind; + + /* Iteration Control Enumeration */ + +typedef enum { + JVMTI_ITERATION_CONTINUE = 1, + JVMTI_ITERATION_IGNORE = 2, + JVMTI_ITERATION_ABORT = 0 +} jvmtiIterationControl; + + /* Class Status Flags */ + +enum { + JVMTI_CLASS_STATUS_VERIFIED = 1, + JVMTI_CLASS_STATUS_PREPARED = 2, + JVMTI_CLASS_STATUS_INITIALIZED = 4, + JVMTI_CLASS_STATUS_ERROR = 8, + JVMTI_CLASS_STATUS_ARRAY = 16, + JVMTI_CLASS_STATUS_PRIMITIVE = 32 +}; + + /* Event Enable/Disable */ + +typedef enum { + JVMTI_ENABLE = 1, + JVMTI_DISABLE = 0 +} jvmtiEventMode; + + /* Extension Function/Event Parameter Types */ + +typedef enum { + JVMTI_TYPE_JBYTE = 101, + JVMTI_TYPE_JCHAR = 102, + JVMTI_TYPE_JSHORT = 103, + JVMTI_TYPE_JINT = 104, + JVMTI_TYPE_JLONG = 105, + JVMTI_TYPE_JFLOAT = 106, + JVMTI_TYPE_JDOUBLE = 107, + JVMTI_TYPE_JBOOLEAN = 108, + JVMTI_TYPE_JOBJECT = 109, + JVMTI_TYPE_JTHREAD = 110, + JVMTI_TYPE_JCLASS = 111, + JVMTI_TYPE_JVALUE = 112, + JVMTI_TYPE_JFIELDID = 113, + JVMTI_TYPE_JMETHODID = 114, + JVMTI_TYPE_CCHAR = 115, + JVMTI_TYPE_CVOID = 116, + JVMTI_TYPE_JNIENV = 117 +} jvmtiParamTypes; + + /* Extension Function/Event Parameter Kinds */ + +typedef enum { + JVMTI_KIND_IN = 91, + JVMTI_KIND_IN_PTR = 92, + JVMTI_KIND_IN_BUF = 93, + JVMTI_KIND_ALLOC_BUF = 94, + JVMTI_KIND_ALLOC_ALLOC_BUF = 95, + JVMTI_KIND_OUT = 96, + JVMTI_KIND_OUT_BUF = 97 +} jvmtiParamKind; + + /* Timer Kinds */ + +typedef enum { + JVMTI_TIMER_USER_CPU = 30, + JVMTI_TIMER_TOTAL_CPU = 31, + JVMTI_TIMER_ELAPSED = 32 +} jvmtiTimerKind; + + /* Phases of execution */ + +typedef enum { + JVMTI_PHASE_ONLOAD = 1, + JVMTI_PHASE_PRIMORDIAL = 2, + JVMTI_PHASE_START = 6, + JVMTI_PHASE_LIVE = 4, + JVMTI_PHASE_DEAD = 8 +} jvmtiPhase; + + /* Version Interface Types */ + +enum { + JVMTI_VERSION_INTERFACE_JNI = 0x00000000, + JVMTI_VERSION_INTERFACE_JVMTI = 0x30000000 +}; + + /* Version Masks */ + +enum { + JVMTI_VERSION_MASK_INTERFACE_TYPE = 0x70000000, + JVMTI_VERSION_MASK_MAJOR = 0x0FFF0000, + JVMTI_VERSION_MASK_MINOR = 0x0000FF00, + JVMTI_VERSION_MASK_MICRO = 0x000000FF +}; + + /* Version Shifts */ + +enum { + JVMTI_VERSION_SHIFT_MAJOR = 16, + JVMTI_VERSION_SHIFT_MINOR = 8, + JVMTI_VERSION_SHIFT_MICRO = 0 +}; + + /* Verbose Flag Enumeration */ + +typedef enum { + JVMTI_VERBOSE_OTHER = 0, + JVMTI_VERBOSE_GC = 1, + JVMTI_VERBOSE_CLASS = 2, + JVMTI_VERBOSE_JNI = 4 +} jvmtiVerboseFlag; + + /* JLocation Format Enumeration */ + +typedef enum { + JVMTI_JLOCATION_JVMBCI = 1, + JVMTI_JLOCATION_MACHINEPC = 2, + JVMTI_JLOCATION_OTHER = 0 +} jvmtiJlocationFormat; + + /* Resource Exhaustion Flags */ + +enum { + JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR = 0x0001, + JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP = 0x0002, + JVMTI_RESOURCE_EXHAUSTED_THREADS = 0x0004 +}; + + /* Errors */ + +typedef enum { + JVMTI_ERROR_NONE = 0, + JVMTI_ERROR_INVALID_THREAD = 10, + JVMTI_ERROR_INVALID_THREAD_GROUP = 11, + JVMTI_ERROR_INVALID_PRIORITY = 12, + JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13, + JVMTI_ERROR_THREAD_SUSPENDED = 14, + JVMTI_ERROR_THREAD_NOT_ALIVE = 15, + JVMTI_ERROR_INVALID_OBJECT = 20, + JVMTI_ERROR_INVALID_CLASS = 21, + JVMTI_ERROR_CLASS_NOT_PREPARED = 22, + JVMTI_ERROR_INVALID_METHODID = 23, + JVMTI_ERROR_INVALID_LOCATION = 24, + JVMTI_ERROR_INVALID_FIELDID = 25, + JVMTI_ERROR_NO_MORE_FRAMES = 31, + JVMTI_ERROR_OPAQUE_FRAME = 32, + JVMTI_ERROR_TYPE_MISMATCH = 34, + JVMTI_ERROR_INVALID_SLOT = 35, + JVMTI_ERROR_DUPLICATE = 40, + JVMTI_ERROR_NOT_FOUND = 41, + JVMTI_ERROR_INVALID_MONITOR = 50, + JVMTI_ERROR_NOT_MONITOR_OWNER = 51, + JVMTI_ERROR_INTERRUPT = 52, + JVMTI_ERROR_INVALID_CLASS_FORMAT = 60, + JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61, + JVMTI_ERROR_FAILS_VERIFICATION = 62, + JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63, + JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64, + JVMTI_ERROR_INVALID_TYPESTATE = 65, + JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66, + JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67, + JVMTI_ERROR_UNSUPPORTED_VERSION = 68, + JVMTI_ERROR_NAMES_DONT_MATCH = 69, + JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70, + JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71, + JVMTI_ERROR_UNMODIFIABLE_CLASS = 79, + JVMTI_ERROR_NOT_AVAILABLE = 98, + JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99, + JVMTI_ERROR_NULL_POINTER = 100, + JVMTI_ERROR_ABSENT_INFORMATION = 101, + JVMTI_ERROR_INVALID_EVENT_TYPE = 102, + JVMTI_ERROR_ILLEGAL_ARGUMENT = 103, + JVMTI_ERROR_NATIVE_METHOD = 104, + JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED = 106, + JVMTI_ERROR_OUT_OF_MEMORY = 110, + JVMTI_ERROR_ACCESS_DENIED = 111, + JVMTI_ERROR_WRONG_PHASE = 112, + JVMTI_ERROR_INTERNAL = 113, + JVMTI_ERROR_UNATTACHED_THREAD = 115, + JVMTI_ERROR_INVALID_ENVIRONMENT = 116, + JVMTI_ERROR_MAX = 116 +} jvmtiError; + + /* Event IDs */ + +typedef enum { + JVMTI_MIN_EVENT_TYPE_VAL = 50, + JVMTI_EVENT_VM_INIT = 50, + JVMTI_EVENT_VM_DEATH = 51, + JVMTI_EVENT_THREAD_START = 52, + JVMTI_EVENT_THREAD_END = 53, + JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54, + JVMTI_EVENT_CLASS_LOAD = 55, + JVMTI_EVENT_CLASS_PREPARE = 56, + JVMTI_EVENT_VM_START = 57, + JVMTI_EVENT_EXCEPTION = 58, + JVMTI_EVENT_EXCEPTION_CATCH = 59, + JVMTI_EVENT_SINGLE_STEP = 60, + JVMTI_EVENT_FRAME_POP = 61, + JVMTI_EVENT_BREAKPOINT = 62, + JVMTI_EVENT_FIELD_ACCESS = 63, + JVMTI_EVENT_FIELD_MODIFICATION = 64, + JVMTI_EVENT_METHOD_ENTRY = 65, + JVMTI_EVENT_METHOD_EXIT = 66, + JVMTI_EVENT_NATIVE_METHOD_BIND = 67, + JVMTI_EVENT_COMPILED_METHOD_LOAD = 68, + JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69, + JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70, + JVMTI_EVENT_DATA_DUMP_REQUEST = 71, + JVMTI_EVENT_MONITOR_WAIT = 73, + JVMTI_EVENT_MONITOR_WAITED = 74, + JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75, + JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76, + JVMTI_EVENT_RESOURCE_EXHAUSTED = 80, + JVMTI_EVENT_GARBAGE_COLLECTION_START = 81, + JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82, + JVMTI_EVENT_OBJECT_FREE = 83, + JVMTI_EVENT_VM_OBJECT_ALLOC = 84, + JVMTI_MAX_EVENT_TYPE_VAL = 84 +} jvmtiEvent; + + + /* Pre-Declarations */ +struct _jvmtiThreadInfo; +typedef struct _jvmtiThreadInfo jvmtiThreadInfo; +struct _jvmtiMonitorStackDepthInfo; +typedef struct _jvmtiMonitorStackDepthInfo jvmtiMonitorStackDepthInfo; +struct _jvmtiThreadGroupInfo; +typedef struct _jvmtiThreadGroupInfo jvmtiThreadGroupInfo; +struct _jvmtiFrameInfo; +typedef struct _jvmtiFrameInfo jvmtiFrameInfo; +struct _jvmtiStackInfo; +typedef struct _jvmtiStackInfo jvmtiStackInfo; +struct _jvmtiHeapReferenceInfoField; +typedef struct _jvmtiHeapReferenceInfoField jvmtiHeapReferenceInfoField; +struct _jvmtiHeapReferenceInfoArray; +typedef struct _jvmtiHeapReferenceInfoArray jvmtiHeapReferenceInfoArray; +struct _jvmtiHeapReferenceInfoConstantPool; +typedef struct _jvmtiHeapReferenceInfoConstantPool jvmtiHeapReferenceInfoConstantPool; +struct _jvmtiHeapReferenceInfoStackLocal; +typedef struct _jvmtiHeapReferenceInfoStackLocal jvmtiHeapReferenceInfoStackLocal; +struct _jvmtiHeapReferenceInfoJniLocal; +typedef struct _jvmtiHeapReferenceInfoJniLocal jvmtiHeapReferenceInfoJniLocal; +struct _jvmtiHeapReferenceInfoReserved; +typedef struct _jvmtiHeapReferenceInfoReserved jvmtiHeapReferenceInfoReserved; +union _jvmtiHeapReferenceInfo; +typedef union _jvmtiHeapReferenceInfo jvmtiHeapReferenceInfo; +struct _jvmtiHeapCallbacks; +typedef struct _jvmtiHeapCallbacks jvmtiHeapCallbacks; +struct _jvmtiClassDefinition; +typedef struct _jvmtiClassDefinition jvmtiClassDefinition; +struct _jvmtiMonitorUsage; +typedef struct _jvmtiMonitorUsage jvmtiMonitorUsage; +struct _jvmtiLineNumberEntry; +typedef struct _jvmtiLineNumberEntry jvmtiLineNumberEntry; +struct _jvmtiLocalVariableEntry; +typedef struct _jvmtiLocalVariableEntry jvmtiLocalVariableEntry; +struct _jvmtiParamInfo; +typedef struct _jvmtiParamInfo jvmtiParamInfo; +struct _jvmtiExtensionFunctionInfo; +typedef struct _jvmtiExtensionFunctionInfo jvmtiExtensionFunctionInfo; +struct _jvmtiExtensionEventInfo; +typedef struct _jvmtiExtensionEventInfo jvmtiExtensionEventInfo; +struct _jvmtiTimerInfo; +typedef struct _jvmtiTimerInfo jvmtiTimerInfo; +struct _jvmtiAddrLocationMap; +typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap; + + /* Function Types */ + +typedef void (JNICALL *jvmtiStartFunction) + (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg); + +typedef jint (JNICALL *jvmtiHeapIterationCallback) + (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data); + +typedef jint (JNICALL *jvmtiHeapReferenceCallback) + (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data); + +typedef jint (JNICALL *jvmtiPrimitiveFieldCallback) + (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data); + +typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback) + (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data); + +typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback) + (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data); + +typedef jint (JNICALL *jvmtiReservedCallback) + (); + +typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback) + (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data); + +typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback) + (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data); + +typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback) + (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data); + +typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback) + (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data); + +typedef jvmtiError (JNICALL *jvmtiExtensionFunction) + (jvmtiEnv* jvmti_env, ...); + +typedef void (JNICALL *jvmtiExtensionEvent) + (jvmtiEnv* jvmti_env, ...); + + + /* Structure Types */ +struct _jvmtiThreadInfo { + char* name; + jint priority; + jboolean is_daemon; + jthreadGroup thread_group; + jobject context_class_loader; +}; +struct _jvmtiMonitorStackDepthInfo { + jobject monitor; + jint stack_depth; +}; +struct _jvmtiThreadGroupInfo { + jthreadGroup parent; + char* name; + jint max_priority; + jboolean is_daemon; +}; +struct _jvmtiFrameInfo { + jmethodID method; + jlocation location; +}; +struct _jvmtiStackInfo { + jthread thread; + jint state; + jvmtiFrameInfo* frame_buffer; + jint frame_count; +}; +struct _jvmtiHeapReferenceInfoField { + jint index; +}; +struct _jvmtiHeapReferenceInfoArray { + jint index; +}; +struct _jvmtiHeapReferenceInfoConstantPool { + jint index; +}; +struct _jvmtiHeapReferenceInfoStackLocal { + jlong thread_tag; + jlong thread_id; + jint depth; + jmethodID method; + jlocation location; + jint slot; +}; +struct _jvmtiHeapReferenceInfoJniLocal { + jlong thread_tag; + jlong thread_id; + jint depth; + jmethodID method; +}; +struct _jvmtiHeapReferenceInfoReserved { + jlong reserved1; + jlong reserved2; + jlong reserved3; + jlong reserved4; + jlong reserved5; + jlong reserved6; + jlong reserved7; + jlong reserved8; +}; +union _jvmtiHeapReferenceInfo { + jvmtiHeapReferenceInfoField field; + jvmtiHeapReferenceInfoArray array; + jvmtiHeapReferenceInfoConstantPool constant_pool; + jvmtiHeapReferenceInfoStackLocal stack_local; + jvmtiHeapReferenceInfoJniLocal jni_local; + jvmtiHeapReferenceInfoReserved other; +}; +struct _jvmtiHeapCallbacks { + jvmtiHeapIterationCallback heap_iteration_callback; + jvmtiHeapReferenceCallback heap_reference_callback; + jvmtiPrimitiveFieldCallback primitive_field_callback; + jvmtiArrayPrimitiveValueCallback array_primitive_value_callback; + jvmtiStringPrimitiveValueCallback string_primitive_value_callback; + jvmtiReservedCallback reserved5; + jvmtiReservedCallback reserved6; + jvmtiReservedCallback reserved7; + jvmtiReservedCallback reserved8; + jvmtiReservedCallback reserved9; + jvmtiReservedCallback reserved10; + jvmtiReservedCallback reserved11; + jvmtiReservedCallback reserved12; + jvmtiReservedCallback reserved13; + jvmtiReservedCallback reserved14; + jvmtiReservedCallback reserved15; +}; +struct _jvmtiClassDefinition { + jclass klass; + jint class_byte_count; + const unsigned char* class_bytes; +}; +struct _jvmtiMonitorUsage { + jthread owner; + jint entry_count; + jint waiter_count; + jthread* waiters; + jint notify_waiter_count; + jthread* notify_waiters; +}; +struct _jvmtiLineNumberEntry { + jlocation start_location; + jint line_number; +}; +struct _jvmtiLocalVariableEntry { + jlocation start_location; + jint length; + char* name; + char* signature; + char* generic_signature; + jint slot; +}; +struct _jvmtiParamInfo { + char* name; + jvmtiParamKind kind; + jvmtiParamTypes base_type; + jboolean null_ok; +}; +struct _jvmtiExtensionFunctionInfo { + jvmtiExtensionFunction func; + char* id; + char* short_description; + jint param_count; + jvmtiParamInfo* params; + jint error_count; + jvmtiError* errors; +}; +struct _jvmtiExtensionEventInfo { + jint extension_event_index; + char* id; + char* short_description; + jint param_count; + jvmtiParamInfo* params; +}; +struct _jvmtiTimerInfo { + jlong max_value; + jboolean may_skip_forward; + jboolean may_skip_backward; + jvmtiTimerKind kind; + jlong reserved1; + jlong reserved2; +}; +struct _jvmtiAddrLocationMap { + const void* start_address; + jlocation location; +}; + +typedef struct { + unsigned int can_tag_objects : 1; + unsigned int can_generate_field_modification_events : 1; + unsigned int can_generate_field_access_events : 1; + unsigned int can_get_bytecodes : 1; + unsigned int can_get_synthetic_attribute : 1; + unsigned int can_get_owned_monitor_info : 1; + unsigned int can_get_current_contended_monitor : 1; + unsigned int can_get_monitor_info : 1; + unsigned int can_pop_frame : 1; + unsigned int can_redefine_classes : 1; + unsigned int can_signal_thread : 1; + unsigned int can_get_source_file_name : 1; + unsigned int can_get_line_numbers : 1; + unsigned int can_get_source_debug_extension : 1; + unsigned int can_access_local_variables : 1; + unsigned int can_maintain_original_method_order : 1; + unsigned int can_generate_single_step_events : 1; + unsigned int can_generate_exception_events : 1; + unsigned int can_generate_frame_pop_events : 1; + unsigned int can_generate_breakpoint_events : 1; + unsigned int can_suspend : 1; + unsigned int can_redefine_any_class : 1; + unsigned int can_get_current_thread_cpu_time : 1; + unsigned int can_get_thread_cpu_time : 1; + unsigned int can_generate_method_entry_events : 1; + unsigned int can_generate_method_exit_events : 1; + unsigned int can_generate_all_class_hook_events : 1; + unsigned int can_generate_compiled_method_load_events : 1; + unsigned int can_generate_monitor_events : 1; + unsigned int can_generate_vm_object_alloc_events : 1; + unsigned int can_generate_native_method_bind_events : 1; + unsigned int can_generate_garbage_collection_events : 1; + unsigned int can_generate_object_free_events : 1; + unsigned int can_force_early_return : 1; + unsigned int can_get_owned_monitor_stack_depth_info : 1; + unsigned int can_get_constant_pool : 1; + unsigned int can_set_native_method_prefix : 1; + unsigned int can_retransform_classes : 1; + unsigned int can_retransform_any_class : 1; + unsigned int can_generate_resource_exhaustion_heap_events : 1; + unsigned int can_generate_resource_exhaustion_threads_events : 1; + unsigned int : 7; + unsigned int : 16; + unsigned int : 16; + unsigned int : 16; + unsigned int : 16; + unsigned int : 16; +} jvmtiCapabilities; + + + /* Event Definitions */ + +typedef void (JNICALL *jvmtiEventReserved)(void); + + +typedef void (JNICALL *jvmtiEventBreakpoint) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jlocation location); + +typedef void (JNICALL *jvmtiEventClassFileLoadHook) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jclass class_being_redefined, + jobject loader, + const char* name, + jobject protection_domain, + jint class_data_len, + const unsigned char* class_data, + jint* new_class_data_len, + unsigned char** new_class_data); + +typedef void (JNICALL *jvmtiEventClassLoad) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jclass klass); + +typedef void (JNICALL *jvmtiEventClassPrepare) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jclass klass); + +typedef void (JNICALL *jvmtiEventCompiledMethodLoad) + (jvmtiEnv *jvmti_env, + jmethodID method, + jint code_size, + const void* code_addr, + jint map_length, + const jvmtiAddrLocationMap* map, + const void* compile_info); + +typedef void (JNICALL *jvmtiEventCompiledMethodUnload) + (jvmtiEnv *jvmti_env, + jmethodID method, + const void* code_addr); + +typedef void (JNICALL *jvmtiEventDataDumpRequest) + (jvmtiEnv *jvmti_env); + +typedef void (JNICALL *jvmtiEventDynamicCodeGenerated) + (jvmtiEnv *jvmti_env, + const char* name, + const void* address, + jint length); + +typedef void (JNICALL *jvmtiEventException) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jlocation location, + jobject exception, + jmethodID catch_method, + jlocation catch_location); + +typedef void (JNICALL *jvmtiEventExceptionCatch) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jlocation location, + jobject exception); + +typedef void (JNICALL *jvmtiEventFieldAccess) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jlocation location, + jclass field_klass, + jobject object, + jfieldID field); + +typedef void (JNICALL *jvmtiEventFieldModification) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jlocation location, + jclass field_klass, + jobject object, + jfieldID field, + char signature_type, + jvalue new_value); + +typedef void (JNICALL *jvmtiEventFramePop) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jboolean was_popped_by_exception); + +typedef void (JNICALL *jvmtiEventGarbageCollectionFinish) + (jvmtiEnv *jvmti_env); + +typedef void (JNICALL *jvmtiEventGarbageCollectionStart) + (jvmtiEnv *jvmti_env); + +typedef void (JNICALL *jvmtiEventMethodEntry) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method); + +typedef void (JNICALL *jvmtiEventMethodExit) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jboolean was_popped_by_exception, + jvalue return_value); + +typedef void (JNICALL *jvmtiEventMonitorContendedEnter) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jobject object); + +typedef void (JNICALL *jvmtiEventMonitorContendedEntered) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jobject object); + +typedef void (JNICALL *jvmtiEventMonitorWait) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jobject object, + jlong timeout); + +typedef void (JNICALL *jvmtiEventMonitorWaited) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jobject object, + jboolean timed_out); + +typedef void (JNICALL *jvmtiEventNativeMethodBind) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + void* address, + void** new_address_ptr); + +typedef void (JNICALL *jvmtiEventObjectFree) + (jvmtiEnv *jvmti_env, + jlong tag); + +typedef void (JNICALL *jvmtiEventResourceExhausted) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jint flags, + const void* reserved, + const char* description); + +typedef void (JNICALL *jvmtiEventSingleStep) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jmethodID method, + jlocation location); + +typedef void (JNICALL *jvmtiEventThreadEnd) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread); + +typedef void (JNICALL *jvmtiEventThreadStart) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread); + +typedef void (JNICALL *jvmtiEventVMDeath) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env); + +typedef void (JNICALL *jvmtiEventVMInit) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread); + +typedef void (JNICALL *jvmtiEventVMObjectAlloc) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread, + jobject object, + jclass object_klass, + jlong size); + +typedef void (JNICALL *jvmtiEventVMStart) + (jvmtiEnv *jvmti_env, + JNIEnv* jni_env); + + /* Event Callback Structure */ + +typedef struct { + /* 50 : VM Initialization Event */ + jvmtiEventVMInit VMInit; + /* 51 : VM Death Event */ + jvmtiEventVMDeath VMDeath; + /* 52 : Thread Start */ + jvmtiEventThreadStart ThreadStart; + /* 53 : Thread End */ + jvmtiEventThreadEnd ThreadEnd; + /* 54 : Class File Load Hook */ + jvmtiEventClassFileLoadHook ClassFileLoadHook; + /* 55 : Class Load */ + jvmtiEventClassLoad ClassLoad; + /* 56 : Class Prepare */ + jvmtiEventClassPrepare ClassPrepare; + /* 57 : VM Start Event */ + jvmtiEventVMStart VMStart; + /* 58 : Exception */ + jvmtiEventException Exception; + /* 59 : Exception Catch */ + jvmtiEventExceptionCatch ExceptionCatch; + /* 60 : Single Step */ + jvmtiEventSingleStep SingleStep; + /* 61 : Frame Pop */ + jvmtiEventFramePop FramePop; + /* 62 : Breakpoint */ + jvmtiEventBreakpoint Breakpoint; + /* 63 : Field Access */ + jvmtiEventFieldAccess FieldAccess; + /* 64 : Field Modification */ + jvmtiEventFieldModification FieldModification; + /* 65 : Method Entry */ + jvmtiEventMethodEntry MethodEntry; + /* 66 : Method Exit */ + jvmtiEventMethodExit MethodExit; + /* 67 : Native Method Bind */ + jvmtiEventNativeMethodBind NativeMethodBind; + /* 68 : Compiled Method Load */ + jvmtiEventCompiledMethodLoad CompiledMethodLoad; + /* 69 : Compiled Method Unload */ + jvmtiEventCompiledMethodUnload CompiledMethodUnload; + /* 70 : Dynamic Code Generated */ + jvmtiEventDynamicCodeGenerated DynamicCodeGenerated; + /* 71 : Data Dump Request */ + jvmtiEventDataDumpRequest DataDumpRequest; + /* 72 */ + jvmtiEventReserved reserved72; + /* 73 : Monitor Wait */ + jvmtiEventMonitorWait MonitorWait; + /* 74 : Monitor Waited */ + jvmtiEventMonitorWaited MonitorWaited; + /* 75 : Monitor Contended Enter */ + jvmtiEventMonitorContendedEnter MonitorContendedEnter; + /* 76 : Monitor Contended Entered */ + jvmtiEventMonitorContendedEntered MonitorContendedEntered; + /* 77 */ + jvmtiEventReserved reserved77; + /* 78 */ + jvmtiEventReserved reserved78; + /* 79 */ + jvmtiEventReserved reserved79; + /* 80 : Resource Exhausted */ + jvmtiEventResourceExhausted ResourceExhausted; + /* 81 : Garbage Collection Start */ + jvmtiEventGarbageCollectionStart GarbageCollectionStart; + /* 82 : Garbage Collection Finish */ + jvmtiEventGarbageCollectionFinish GarbageCollectionFinish; + /* 83 : Object Free */ + jvmtiEventObjectFree ObjectFree; + /* 84 : VM Object Allocation */ + jvmtiEventVMObjectAlloc VMObjectAlloc; +} jvmtiEventCallbacks; + + + /* Function Interface */ + +typedef struct jvmtiInterface_1_ { + + /* 1 : RESERVED */ + void *reserved1; + + /* 2 : Set Event Notification Mode */ + jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env, + jvmtiEventMode mode, + jvmtiEvent event_type, + jthread event_thread, + ...); + + /* 3 : RESERVED */ + void *reserved3; + + /* 4 : Get All Threads */ + jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env, + jint* threads_count_ptr, + jthread** threads_ptr); + + /* 5 : Suspend Thread */ + jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env, + jthread thread); + + /* 6 : Resume Thread */ + jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env, + jthread thread); + + /* 7 : Stop Thread */ + jvmtiError (JNICALL *StopThread) (jvmtiEnv* env, + jthread thread, + jobject exception); + + /* 8 : Interrupt Thread */ + jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env, + jthread thread); + + /* 9 : Get Thread Info */ + jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env, + jthread thread, + jvmtiThreadInfo* info_ptr); + + /* 10 : Get Owned Monitor Info */ + jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env, + jthread thread, + jint* owned_monitor_count_ptr, + jobject** owned_monitors_ptr); + + /* 11 : Get Current Contended Monitor */ + jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env, + jthread thread, + jobject* monitor_ptr); + + /* 12 : Run Agent Thread */ + jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env, + jthread thread, + jvmtiStartFunction proc, + const void* arg, + jint priority); + + /* 13 : Get Top Thread Groups */ + jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env, + jint* group_count_ptr, + jthreadGroup** groups_ptr); + + /* 14 : Get Thread Group Info */ + jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env, + jthreadGroup group, + jvmtiThreadGroupInfo* info_ptr); + + /* 15 : Get Thread Group Children */ + jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env, + jthreadGroup group, + jint* thread_count_ptr, + jthread** threads_ptr, + jint* group_count_ptr, + jthreadGroup** groups_ptr); + + /* 16 : Get Frame Count */ + jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env, + jthread thread, + jint* count_ptr); + + /* 17 : Get Thread State */ + jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env, + jthread thread, + jint* thread_state_ptr); + + /* 18 : Get Current Thread */ + jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env, + jthread* thread_ptr); + + /* 19 : Get Frame Location */ + jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env, + jthread thread, + jint depth, + jmethodID* method_ptr, + jlocation* location_ptr); + + /* 20 : Notify Frame Pop */ + jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env, + jthread thread, + jint depth); + + /* 21 : Get Local Variable - Object */ + jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jobject* value_ptr); + + /* 22 : Get Local Variable - Int */ + jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jint* value_ptr); + + /* 23 : Get Local Variable - Long */ + jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jlong* value_ptr); + + /* 24 : Get Local Variable - Float */ + jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jfloat* value_ptr); + + /* 25 : Get Local Variable - Double */ + jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jdouble* value_ptr); + + /* 26 : Set Local Variable - Object */ + jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jobject value); + + /* 27 : Set Local Variable - Int */ + jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jint value); + + /* 28 : Set Local Variable - Long */ + jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jlong value); + + /* 29 : Set Local Variable - Float */ + jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jfloat value); + + /* 30 : Set Local Variable - Double */ + jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env, + jthread thread, + jint depth, + jint slot, + jdouble value); + + /* 31 : Create Raw Monitor */ + jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env, + const char* name, + jrawMonitorID* monitor_ptr); + + /* 32 : Destroy Raw Monitor */ + jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env, + jrawMonitorID monitor); + + /* 33 : Raw Monitor Enter */ + jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env, + jrawMonitorID monitor); + + /* 34 : Raw Monitor Exit */ + jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env, + jrawMonitorID monitor); + + /* 35 : Raw Monitor Wait */ + jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env, + jrawMonitorID monitor, + jlong millis); + + /* 36 : Raw Monitor Notify */ + jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env, + jrawMonitorID monitor); + + /* 37 : Raw Monitor Notify All */ + jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env, + jrawMonitorID monitor); + + /* 38 : Set Breakpoint */ + jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env, + jmethodID method, + jlocation location); + + /* 39 : Clear Breakpoint */ + jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env, + jmethodID method, + jlocation location); + + /* 40 : RESERVED */ + void *reserved40; + + /* 41 : Set Field Access Watch */ + jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env, + jclass klass, + jfieldID field); + + /* 42 : Clear Field Access Watch */ + jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env, + jclass klass, + jfieldID field); + + /* 43 : Set Field Modification Watch */ + jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env, + jclass klass, + jfieldID field); + + /* 44 : Clear Field Modification Watch */ + jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env, + jclass klass, + jfieldID field); + + /* 45 : Is Modifiable Class */ + jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env, + jclass klass, + jboolean* is_modifiable_class_ptr); + + /* 46 : Allocate */ + jvmtiError (JNICALL *Allocate) (jvmtiEnv* env, + jlong size, + unsigned char** mem_ptr); + + /* 47 : Deallocate */ + jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env, + unsigned char* mem); + + /* 48 : Get Class Signature */ + jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env, + jclass klass, + char** signature_ptr, + char** generic_ptr); + + /* 49 : Get Class Status */ + jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env, + jclass klass, + jint* status_ptr); + + /* 50 : Get Source File Name */ + jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env, + jclass klass, + char** source_name_ptr); + + /* 51 : Get Class Modifiers */ + jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env, + jclass klass, + jint* modifiers_ptr); + + /* 52 : Get Class Methods */ + jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env, + jclass klass, + jint* method_count_ptr, + jmethodID** methods_ptr); + + /* 53 : Get Class Fields */ + jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env, + jclass klass, + jint* field_count_ptr, + jfieldID** fields_ptr); + + /* 54 : Get Implemented Interfaces */ + jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env, + jclass klass, + jint* interface_count_ptr, + jclass** interfaces_ptr); + + /* 55 : Is Interface */ + jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env, + jclass klass, + jboolean* is_interface_ptr); + + /* 56 : Is Array Class */ + jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env, + jclass klass, + jboolean* is_array_class_ptr); + + /* 57 : Get Class Loader */ + jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env, + jclass klass, + jobject* classloader_ptr); + + /* 58 : Get Object Hash Code */ + jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env, + jobject object, + jint* hash_code_ptr); + + /* 59 : Get Object Monitor Usage */ + jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env, + jobject object, + jvmtiMonitorUsage* info_ptr); + + /* 60 : Get Field Name (and Signature) */ + jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env, + jclass klass, + jfieldID field, + char** name_ptr, + char** signature_ptr, + char** generic_ptr); + + /* 61 : Get Field Declaring Class */ + jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env, + jclass klass, + jfieldID field, + jclass* declaring_class_ptr); + + /* 62 : Get Field Modifiers */ + jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env, + jclass klass, + jfieldID field, + jint* modifiers_ptr); + + /* 63 : Is Field Synthetic */ + jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env, + jclass klass, + jfieldID field, + jboolean* is_synthetic_ptr); + + /* 64 : Get Method Name (and Signature) */ + jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env, + jmethodID method, + char** name_ptr, + char** signature_ptr, + char** generic_ptr); + + /* 65 : Get Method Declaring Class */ + jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env, + jmethodID method, + jclass* declaring_class_ptr); + + /* 66 : Get Method Modifiers */ + jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env, + jmethodID method, + jint* modifiers_ptr); + + /* 67 : RESERVED */ + void *reserved67; + + /* 68 : Get Max Locals */ + jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env, + jmethodID method, + jint* max_ptr); + + /* 69 : Get Arguments Size */ + jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env, + jmethodID method, + jint* size_ptr); + + /* 70 : Get Line Number Table */ + jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env, + jmethodID method, + jint* entry_count_ptr, + jvmtiLineNumberEntry** table_ptr); + + /* 71 : Get Method Location */ + jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env, + jmethodID method, + jlocation* start_location_ptr, + jlocation* end_location_ptr); + + /* 72 : Get Local Variable Table */ + jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env, + jmethodID method, + jint* entry_count_ptr, + jvmtiLocalVariableEntry** table_ptr); + + /* 73 : Set Native Method Prefix */ + jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env, + const char* prefix); + + /* 74 : Set Native Method Prefixes */ + jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env, + jint prefix_count, + char** prefixes); + + /* 75 : Get Bytecodes */ + jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env, + jmethodID method, + jint* bytecode_count_ptr, + unsigned char** bytecodes_ptr); + + /* 76 : Is Method Native */ + jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env, + jmethodID method, + jboolean* is_native_ptr); + + /* 77 : Is Method Synthetic */ + jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env, + jmethodID method, + jboolean* is_synthetic_ptr); + + /* 78 : Get Loaded Classes */ + jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env, + jint* class_count_ptr, + jclass** classes_ptr); + + /* 79 : Get Classloader Classes */ + jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env, + jobject initiating_loader, + jint* class_count_ptr, + jclass** classes_ptr); + + /* 80 : Pop Frame */ + jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env, + jthread thread); + + /* 81 : Force Early Return - Object */ + jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env, + jthread thread, + jobject value); + + /* 82 : Force Early Return - Int */ + jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env, + jthread thread, + jint value); + + /* 83 : Force Early Return - Long */ + jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env, + jthread thread, + jlong value); + + /* 84 : Force Early Return - Float */ + jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env, + jthread thread, + jfloat value); + + /* 85 : Force Early Return - Double */ + jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env, + jthread thread, + jdouble value); + + /* 86 : Force Early Return - Void */ + jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env, + jthread thread); + + /* 87 : Redefine Classes */ + jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env, + jint class_count, + const jvmtiClassDefinition* class_definitions); + + /* 88 : Get Version Number */ + jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env, + jint* version_ptr); + + /* 89 : Get Capabilities */ + jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env, + jvmtiCapabilities* capabilities_ptr); + + /* 90 : Get Source Debug Extension */ + jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env, + jclass klass, + char** source_debug_extension_ptr); + + /* 91 : Is Method Obsolete */ + jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env, + jmethodID method, + jboolean* is_obsolete_ptr); + + /* 92 : Suspend Thread List */ + jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env, + jint request_count, + const jthread* request_list, + jvmtiError* results); + + /* 93 : Resume Thread List */ + jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env, + jint request_count, + const jthread* request_list, + jvmtiError* results); + + /* 94 : RESERVED */ + void *reserved94; + + /* 95 : RESERVED */ + void *reserved95; + + /* 96 : RESERVED */ + void *reserved96; + + /* 97 : RESERVED */ + void *reserved97; + + /* 98 : RESERVED */ + void *reserved98; + + /* 99 : RESERVED */ + void *reserved99; + + /* 100 : Get All Stack Traces */ + jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env, + jint max_frame_count, + jvmtiStackInfo** stack_info_ptr, + jint* thread_count_ptr); + + /* 101 : Get Thread List Stack Traces */ + jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env, + jint thread_count, + const jthread* thread_list, + jint max_frame_count, + jvmtiStackInfo** stack_info_ptr); + + /* 102 : Get Thread Local Storage */ + jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env, + jthread thread, + void** data_ptr); + + /* 103 : Set Thread Local Storage */ + jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env, + jthread thread, + const void* data); + + /* 104 : Get Stack Trace */ + jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env, + jthread thread, + jint start_depth, + jint max_frame_count, + jvmtiFrameInfo* frame_buffer, + jint* count_ptr); + + /* 105 : RESERVED */ + void *reserved105; + + /* 106 : Get Tag */ + jvmtiError (JNICALL *GetTag) (jvmtiEnv* env, + jobject object, + jlong* tag_ptr); + + /* 107 : Set Tag */ + jvmtiError (JNICALL *SetTag) (jvmtiEnv* env, + jobject object, + jlong tag); + + /* 108 : Force Garbage Collection */ + jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env); + + /* 109 : Iterate Over Objects Reachable From Object */ + jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env, + jobject object, + jvmtiObjectReferenceCallback object_reference_callback, + const void* user_data); + + /* 110 : Iterate Over Reachable Objects */ + jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env, + jvmtiHeapRootCallback heap_root_callback, + jvmtiStackReferenceCallback stack_ref_callback, + jvmtiObjectReferenceCallback object_ref_callback, + const void* user_data); + + /* 111 : Iterate Over Heap */ + jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env, + jvmtiHeapObjectFilter object_filter, + jvmtiHeapObjectCallback heap_object_callback, + const void* user_data); + + /* 112 : Iterate Over Instances Of Class */ + jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env, + jclass klass, + jvmtiHeapObjectFilter object_filter, + jvmtiHeapObjectCallback heap_object_callback, + const void* user_data); + + /* 113 : RESERVED */ + void *reserved113; + + /* 114 : Get Objects With Tags */ + jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env, + jint tag_count, + const jlong* tags, + jint* count_ptr, + jobject** object_result_ptr, + jlong** tag_result_ptr); + + /* 115 : Follow References */ + jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env, + jint heap_filter, + jclass klass, + jobject initial_object, + const jvmtiHeapCallbacks* callbacks, + const void* user_data); + + /* 116 : Iterate Through Heap */ + jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env, + jint heap_filter, + jclass klass, + const jvmtiHeapCallbacks* callbacks, + const void* user_data); + + /* 117 : RESERVED */ + void *reserved117; + + /* 118 : RESERVED */ + void *reserved118; + + /* 119 : RESERVED */ + void *reserved119; + + /* 120 : Set JNI Function Table */ + jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env, + const jniNativeInterface* function_table); + + /* 121 : Get JNI Function Table */ + jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env, + jniNativeInterface** function_table); + + /* 122 : Set Event Callbacks */ + jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env, + const jvmtiEventCallbacks* callbacks, + jint size_of_callbacks); + + /* 123 : Generate Events */ + jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env, + jvmtiEvent event_type); + + /* 124 : Get Extension Functions */ + jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env, + jint* extension_count_ptr, + jvmtiExtensionFunctionInfo** extensions); + + /* 125 : Get Extension Events */ + jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env, + jint* extension_count_ptr, + jvmtiExtensionEventInfo** extensions); + + /* 126 : Set Extension Event Callback */ + jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env, + jint extension_event_index, + jvmtiExtensionEvent callback); + + /* 127 : Dispose Environment */ + jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env); + + /* 128 : Get Error Name */ + jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env, + jvmtiError error, + char** name_ptr); + + /* 129 : Get JLocation Format */ + jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env, + jvmtiJlocationFormat* format_ptr); + + /* 130 : Get System Properties */ + jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env, + jint* count_ptr, + char*** property_ptr); + + /* 131 : Get System Property */ + jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env, + const char* property, + char** value_ptr); + + /* 132 : Set System Property */ + jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env, + const char* property, + const char* value); + + /* 133 : Get Phase */ + jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env, + jvmtiPhase* phase_ptr); + + /* 134 : Get Current Thread CPU Timer Information */ + jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env, + jvmtiTimerInfo* info_ptr); + + /* 135 : Get Current Thread CPU Time */ + jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env, + jlong* nanos_ptr); + + /* 136 : Get Thread CPU Timer Information */ + jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env, + jvmtiTimerInfo* info_ptr); + + /* 137 : Get Thread CPU Time */ + jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env, + jthread thread, + jlong* nanos_ptr); + + /* 138 : Get Timer Information */ + jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env, + jvmtiTimerInfo* info_ptr); + + /* 139 : Get Time */ + jvmtiError (JNICALL *GetTime) (jvmtiEnv* env, + jlong* nanos_ptr); + + /* 140 : Get Potential Capabilities */ + jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env, + jvmtiCapabilities* capabilities_ptr); + + /* 141 : RESERVED */ + void *reserved141; + + /* 142 : Add Capabilities */ + jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env, + const jvmtiCapabilities* capabilities_ptr); + + /* 143 : Relinquish Capabilities */ + jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env, + const jvmtiCapabilities* capabilities_ptr); + + /* 144 : Get Available Processors */ + jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env, + jint* processor_count_ptr); + + /* 145 : Get Class Version Numbers */ + jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env, + jclass klass, + jint* minor_version_ptr, + jint* major_version_ptr); + + /* 146 : Get Constant Pool */ + jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env, + jclass klass, + jint* constant_pool_count_ptr, + jint* constant_pool_byte_count_ptr, + unsigned char** constant_pool_bytes_ptr); + + /* 147 : Get Environment Local Storage */ + jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env, + void** data_ptr); + + /* 148 : Set Environment Local Storage */ + jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env, + const void* data); + + /* 149 : Add To Bootstrap Class Loader Search */ + jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env, + const char* segment); + + /* 150 : Set Verbose Flag */ + jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env, + jvmtiVerboseFlag flag, + jboolean value); + + /* 151 : Add To System Class Loader Search */ + jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env, + const char* segment); + + /* 152 : Retransform Classes */ + jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env, + jint class_count, + const jclass* classes); + + /* 153 : Get Owned Monitor Stack Depth Info */ + jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env, + jthread thread, + jint* monitor_info_count_ptr, + jvmtiMonitorStackDepthInfo** monitor_info_ptr); + + /* 154 : Get Object Size */ + jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env, + jobject object, + jlong* size_ptr); + + /* 155 : Get Local Instance */ + jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env, + jthread thread, + jint depth, + jobject* value_ptr); + +} jvmtiInterface_1; + +struct _jvmtiEnv { + const struct jvmtiInterface_1_ *functions; +#ifdef __cplusplus + + + jvmtiError Allocate(jlong size, + unsigned char** mem_ptr) { + return functions->Allocate(this, size, mem_ptr); + } + + jvmtiError Deallocate(unsigned char* mem) { + return functions->Deallocate(this, mem); + } + + jvmtiError GetThreadState(jthread thread, + jint* thread_state_ptr) { + return functions->GetThreadState(this, thread, thread_state_ptr); + } + + jvmtiError GetCurrentThread(jthread* thread_ptr) { + return functions->GetCurrentThread(this, thread_ptr); + } + + jvmtiError GetAllThreads(jint* threads_count_ptr, + jthread** threads_ptr) { + return functions->GetAllThreads(this, threads_count_ptr, threads_ptr); + } + + jvmtiError SuspendThread(jthread thread) { + return functions->SuspendThread(this, thread); + } + + jvmtiError SuspendThreadList(jint request_count, + const jthread* request_list, + jvmtiError* results) { + return functions->SuspendThreadList(this, request_count, request_list, results); + } + + jvmtiError ResumeThread(jthread thread) { + return functions->ResumeThread(this, thread); + } + + jvmtiError ResumeThreadList(jint request_count, + const jthread* request_list, + jvmtiError* results) { + return functions->ResumeThreadList(this, request_count, request_list, results); + } + + jvmtiError StopThread(jthread thread, + jobject exception) { + return functions->StopThread(this, thread, exception); + } + + jvmtiError InterruptThread(jthread thread) { + return functions->InterruptThread(this, thread); + } + + jvmtiError GetThreadInfo(jthread thread, + jvmtiThreadInfo* info_ptr) { + return functions->GetThreadInfo(this, thread, info_ptr); + } + + jvmtiError GetOwnedMonitorInfo(jthread thread, + jint* owned_monitor_count_ptr, + jobject** owned_monitors_ptr) { + return functions->GetOwnedMonitorInfo(this, thread, owned_monitor_count_ptr, owned_monitors_ptr); + } + + jvmtiError GetOwnedMonitorStackDepthInfo(jthread thread, + jint* monitor_info_count_ptr, + jvmtiMonitorStackDepthInfo** monitor_info_ptr) { + return functions->GetOwnedMonitorStackDepthInfo(this, thread, monitor_info_count_ptr, monitor_info_ptr); + } + + jvmtiError GetCurrentContendedMonitor(jthread thread, + jobject* monitor_ptr) { + return functions->GetCurrentContendedMonitor(this, thread, monitor_ptr); + } + + jvmtiError RunAgentThread(jthread thread, + jvmtiStartFunction proc, + const void* arg, + jint priority) { + return functions->RunAgentThread(this, thread, proc, arg, priority); + } + + jvmtiError SetThreadLocalStorage(jthread thread, + const void* data) { + return functions->SetThreadLocalStorage(this, thread, data); + } + + jvmtiError GetThreadLocalStorage(jthread thread, + void** data_ptr) { + return functions->GetThreadLocalStorage(this, thread, data_ptr); + } + + jvmtiError GetTopThreadGroups(jint* group_count_ptr, + jthreadGroup** groups_ptr) { + return functions->GetTopThreadGroups(this, group_count_ptr, groups_ptr); + } + + jvmtiError GetThreadGroupInfo(jthreadGroup group, + jvmtiThreadGroupInfo* info_ptr) { + return functions->GetThreadGroupInfo(this, group, info_ptr); + } + + jvmtiError GetThreadGroupChildren(jthreadGroup group, + jint* thread_count_ptr, + jthread** threads_ptr, + jint* group_count_ptr, + jthreadGroup** groups_ptr) { + return functions->GetThreadGroupChildren(this, group, thread_count_ptr, threads_ptr, group_count_ptr, groups_ptr); + } + + jvmtiError GetStackTrace(jthread thread, + jint start_depth, + jint max_frame_count, + jvmtiFrameInfo* frame_buffer, + jint* count_ptr) { + return functions->GetStackTrace(this, thread, start_depth, max_frame_count, frame_buffer, count_ptr); + } + + jvmtiError GetAllStackTraces(jint max_frame_count, + jvmtiStackInfo** stack_info_ptr, + jint* thread_count_ptr) { + return functions->GetAllStackTraces(this, max_frame_count, stack_info_ptr, thread_count_ptr); + } + + jvmtiError GetThreadListStackTraces(jint thread_count, + const jthread* thread_list, + jint max_frame_count, + jvmtiStackInfo** stack_info_ptr) { + return functions->GetThreadListStackTraces(this, thread_count, thread_list, max_frame_count, stack_info_ptr); + } + + jvmtiError GetFrameCount(jthread thread, + jint* count_ptr) { + return functions->GetFrameCount(this, thread, count_ptr); + } + + jvmtiError PopFrame(jthread thread) { + return functions->PopFrame(this, thread); + } + + jvmtiError GetFrameLocation(jthread thread, + jint depth, + jmethodID* method_ptr, + jlocation* location_ptr) { + return functions->GetFrameLocation(this, thread, depth, method_ptr, location_ptr); + } + + jvmtiError NotifyFramePop(jthread thread, + jint depth) { + return functions->NotifyFramePop(this, thread, depth); + } + + jvmtiError ForceEarlyReturnObject(jthread thread, + jobject value) { + return functions->ForceEarlyReturnObject(this, thread, value); + } + + jvmtiError ForceEarlyReturnInt(jthread thread, + jint value) { + return functions->ForceEarlyReturnInt(this, thread, value); + } + + jvmtiError ForceEarlyReturnLong(jthread thread, + jlong value) { + return functions->ForceEarlyReturnLong(this, thread, value); + } + + jvmtiError ForceEarlyReturnFloat(jthread thread, + jfloat value) { + return functions->ForceEarlyReturnFloat(this, thread, value); + } + + jvmtiError ForceEarlyReturnDouble(jthread thread, + jdouble value) { + return functions->ForceEarlyReturnDouble(this, thread, value); + } + + jvmtiError ForceEarlyReturnVoid(jthread thread) { + return functions->ForceEarlyReturnVoid(this, thread); + } + + jvmtiError FollowReferences(jint heap_filter, + jclass klass, + jobject initial_object, + const jvmtiHeapCallbacks* callbacks, + const void* user_data) { + return functions->FollowReferences(this, heap_filter, klass, initial_object, callbacks, user_data); + } + + jvmtiError IterateThroughHeap(jint heap_filter, + jclass klass, + const jvmtiHeapCallbacks* callbacks, + const void* user_data) { + return functions->IterateThroughHeap(this, heap_filter, klass, callbacks, user_data); + } + + jvmtiError GetTag(jobject object, + jlong* tag_ptr) { + return functions->GetTag(this, object, tag_ptr); + } + + jvmtiError SetTag(jobject object, + jlong tag) { + return functions->SetTag(this, object, tag); + } + + jvmtiError GetObjectsWithTags(jint tag_count, + const jlong* tags, + jint* count_ptr, + jobject** object_result_ptr, + jlong** tag_result_ptr) { + return functions->GetObjectsWithTags(this, tag_count, tags, count_ptr, object_result_ptr, tag_result_ptr); + } + + jvmtiError ForceGarbageCollection() { + return functions->ForceGarbageCollection(this); + } + + jvmtiError IterateOverObjectsReachableFromObject(jobject object, + jvmtiObjectReferenceCallback object_reference_callback, + const void* user_data) { + return functions->IterateOverObjectsReachableFromObject(this, object, object_reference_callback, user_data); + } + + jvmtiError IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback, + jvmtiStackReferenceCallback stack_ref_callback, + jvmtiObjectReferenceCallback object_ref_callback, + const void* user_data) { + return functions->IterateOverReachableObjects(this, heap_root_callback, stack_ref_callback, object_ref_callback, user_data); + } + + jvmtiError IterateOverHeap(jvmtiHeapObjectFilter object_filter, + jvmtiHeapObjectCallback heap_object_callback, + const void* user_data) { + return functions->IterateOverHeap(this, object_filter, heap_object_callback, user_data); + } + + jvmtiError IterateOverInstancesOfClass(jclass klass, + jvmtiHeapObjectFilter object_filter, + jvmtiHeapObjectCallback heap_object_callback, + const void* user_data) { + return functions->IterateOverInstancesOfClass(this, klass, object_filter, heap_object_callback, user_data); + } + + jvmtiError GetLocalObject(jthread thread, + jint depth, + jint slot, + jobject* value_ptr) { + return functions->GetLocalObject(this, thread, depth, slot, value_ptr); + } + + jvmtiError GetLocalInstance(jthread thread, + jint depth, + jobject* value_ptr) { + return functions->GetLocalInstance(this, thread, depth, value_ptr); + } + + jvmtiError GetLocalInt(jthread thread, + jint depth, + jint slot, + jint* value_ptr) { + return functions->GetLocalInt(this, thread, depth, slot, value_ptr); + } + + jvmtiError GetLocalLong(jthread thread, + jint depth, + jint slot, + jlong* value_ptr) { + return functions->GetLocalLong(this, thread, depth, slot, value_ptr); + } + + jvmtiError GetLocalFloat(jthread thread, + jint depth, + jint slot, + jfloat* value_ptr) { + return functions->GetLocalFloat(this, thread, depth, slot, value_ptr); + } + + jvmtiError GetLocalDouble(jthread thread, + jint depth, + jint slot, + jdouble* value_ptr) { + return functions->GetLocalDouble(this, thread, depth, slot, value_ptr); + } + + jvmtiError SetLocalObject(jthread thread, + jint depth, + jint slot, + jobject value) { + return functions->SetLocalObject(this, thread, depth, slot, value); + } + + jvmtiError SetLocalInt(jthread thread, + jint depth, + jint slot, + jint value) { + return functions->SetLocalInt(this, thread, depth, slot, value); + } + + jvmtiError SetLocalLong(jthread thread, + jint depth, + jint slot, + jlong value) { + return functions->SetLocalLong(this, thread, depth, slot, value); + } + + jvmtiError SetLocalFloat(jthread thread, + jint depth, + jint slot, + jfloat value) { + return functions->SetLocalFloat(this, thread, depth, slot, value); + } + + jvmtiError SetLocalDouble(jthread thread, + jint depth, + jint slot, + jdouble value) { + return functions->SetLocalDouble(this, thread, depth, slot, value); + } + + jvmtiError SetBreakpoint(jmethodID method, + jlocation location) { + return functions->SetBreakpoint(this, method, location); + } + + jvmtiError ClearBreakpoint(jmethodID method, + jlocation location) { + return functions->ClearBreakpoint(this, method, location); + } + + jvmtiError SetFieldAccessWatch(jclass klass, + jfieldID field) { + return functions->SetFieldAccessWatch(this, klass, field); + } + + jvmtiError ClearFieldAccessWatch(jclass klass, + jfieldID field) { + return functions->ClearFieldAccessWatch(this, klass, field); + } + + jvmtiError SetFieldModificationWatch(jclass klass, + jfieldID field) { + return functions->SetFieldModificationWatch(this, klass, field); + } + + jvmtiError ClearFieldModificationWatch(jclass klass, + jfieldID field) { + return functions->ClearFieldModificationWatch(this, klass, field); + } + + jvmtiError GetLoadedClasses(jint* class_count_ptr, + jclass** classes_ptr) { + return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr); + } + + jvmtiError GetClassLoaderClasses(jobject initiating_loader, + jint* class_count_ptr, + jclass** classes_ptr) { + return functions->GetClassLoaderClasses(this, initiating_loader, class_count_ptr, classes_ptr); + } + + jvmtiError GetClassSignature(jclass klass, + char** signature_ptr, + char** generic_ptr) { + return functions->GetClassSignature(this, klass, signature_ptr, generic_ptr); + } + + jvmtiError GetClassStatus(jclass klass, + jint* status_ptr) { + return functions->GetClassStatus(this, klass, status_ptr); + } + + jvmtiError GetSourceFileName(jclass klass, + char** source_name_ptr) { + return functions->GetSourceFileName(this, klass, source_name_ptr); + } + + jvmtiError GetClassModifiers(jclass klass, + jint* modifiers_ptr) { + return functions->GetClassModifiers(this, klass, modifiers_ptr); + } + + jvmtiError GetClassMethods(jclass klass, + jint* method_count_ptr, + jmethodID** methods_ptr) { + return functions->GetClassMethods(this, klass, method_count_ptr, methods_ptr); + } + + jvmtiError GetClassFields(jclass klass, + jint* field_count_ptr, + jfieldID** fields_ptr) { + return functions->GetClassFields(this, klass, field_count_ptr, fields_ptr); + } + + jvmtiError GetImplementedInterfaces(jclass klass, + jint* interface_count_ptr, + jclass** interfaces_ptr) { + return functions->GetImplementedInterfaces(this, klass, interface_count_ptr, interfaces_ptr); + } + + jvmtiError GetClassVersionNumbers(jclass klass, + jint* minor_version_ptr, + jint* major_version_ptr) { + return functions->GetClassVersionNumbers(this, klass, minor_version_ptr, major_version_ptr); + } + + jvmtiError GetConstantPool(jclass klass, + jint* constant_pool_count_ptr, + jint* constant_pool_byte_count_ptr, + unsigned char** constant_pool_bytes_ptr) { + return functions->GetConstantPool(this, klass, constant_pool_count_ptr, constant_pool_byte_count_ptr, constant_pool_bytes_ptr); + } + + jvmtiError IsInterface(jclass klass, + jboolean* is_interface_ptr) { + return functions->IsInterface(this, klass, is_interface_ptr); + } + + jvmtiError IsArrayClass(jclass klass, + jboolean* is_array_class_ptr) { + return functions->IsArrayClass(this, klass, is_array_class_ptr); + } + + jvmtiError IsModifiableClass(jclass klass, + jboolean* is_modifiable_class_ptr) { + return functions->IsModifiableClass(this, klass, is_modifiable_class_ptr); + } + + jvmtiError GetClassLoader(jclass klass, + jobject* classloader_ptr) { + return functions->GetClassLoader(this, klass, classloader_ptr); + } + + jvmtiError GetSourceDebugExtension(jclass klass, + char** source_debug_extension_ptr) { + return functions->GetSourceDebugExtension(this, klass, source_debug_extension_ptr); + } + + jvmtiError RetransformClasses(jint class_count, + const jclass* classes) { + return functions->RetransformClasses(this, class_count, classes); + } + + jvmtiError RedefineClasses(jint class_count, + const jvmtiClassDefinition* class_definitions) { + return functions->RedefineClasses(this, class_count, class_definitions); + } + + jvmtiError GetObjectSize(jobject object, + jlong* size_ptr) { + return functions->GetObjectSize(this, object, size_ptr); + } + + jvmtiError GetObjectHashCode(jobject object, + jint* hash_code_ptr) { + return functions->GetObjectHashCode(this, object, hash_code_ptr); + } + + jvmtiError GetObjectMonitorUsage(jobject object, + jvmtiMonitorUsage* info_ptr) { + return functions->GetObjectMonitorUsage(this, object, info_ptr); + } + + jvmtiError GetFieldName(jclass klass, + jfieldID field, + char** name_ptr, + char** signature_ptr, + char** generic_ptr) { + return functions->GetFieldName(this, klass, field, name_ptr, signature_ptr, generic_ptr); + } + + jvmtiError GetFieldDeclaringClass(jclass klass, + jfieldID field, + jclass* declaring_class_ptr) { + return functions->GetFieldDeclaringClass(this, klass, field, declaring_class_ptr); + } + + jvmtiError GetFieldModifiers(jclass klass, + jfieldID field, + jint* modifiers_ptr) { + return functions->GetFieldModifiers(this, klass, field, modifiers_ptr); + } + + jvmtiError IsFieldSynthetic(jclass klass, + jfieldID field, + jboolean* is_synthetic_ptr) { + return functions->IsFieldSynthetic(this, klass, field, is_synthetic_ptr); + } + + jvmtiError GetMethodName(jmethodID method, + char** name_ptr, + char** signature_ptr, + char** generic_ptr) { + return functions->GetMethodName(this, method, name_ptr, signature_ptr, generic_ptr); + } + + jvmtiError GetMethodDeclaringClass(jmethodID method, + jclass* declaring_class_ptr) { + return functions->GetMethodDeclaringClass(this, method, declaring_class_ptr); + } + + jvmtiError GetMethodModifiers(jmethodID method, + jint* modifiers_ptr) { + return functions->GetMethodModifiers(this, method, modifiers_ptr); + } + + jvmtiError GetMaxLocals(jmethodID method, + jint* max_ptr) { + return functions->GetMaxLocals(this, method, max_ptr); + } + + jvmtiError GetArgumentsSize(jmethodID method, + jint* size_ptr) { + return functions->GetArgumentsSize(this, method, size_ptr); + } + + jvmtiError GetLineNumberTable(jmethodID method, + jint* entry_count_ptr, + jvmtiLineNumberEntry** table_ptr) { + return functions->GetLineNumberTable(this, method, entry_count_ptr, table_ptr); + } + + jvmtiError GetMethodLocation(jmethodID method, + jlocation* start_location_ptr, + jlocation* end_location_ptr) { + return functions->GetMethodLocation(this, method, start_location_ptr, end_location_ptr); + } + + jvmtiError GetLocalVariableTable(jmethodID method, + jint* entry_count_ptr, + jvmtiLocalVariableEntry** table_ptr) { + return functions->GetLocalVariableTable(this, method, entry_count_ptr, table_ptr); + } + + jvmtiError GetBytecodes(jmethodID method, + jint* bytecode_count_ptr, + unsigned char** bytecodes_ptr) { + return functions->GetBytecodes(this, method, bytecode_count_ptr, bytecodes_ptr); + } + + jvmtiError IsMethodNative(jmethodID method, + jboolean* is_native_ptr) { + return functions->IsMethodNative(this, method, is_native_ptr); + } + + jvmtiError IsMethodSynthetic(jmethodID method, + jboolean* is_synthetic_ptr) { + return functions->IsMethodSynthetic(this, method, is_synthetic_ptr); + } + + jvmtiError IsMethodObsolete(jmethodID method, + jboolean* is_obsolete_ptr) { + return functions->IsMethodObsolete(this, method, is_obsolete_ptr); + } + + jvmtiError SetNativeMethodPrefix(const char* prefix) { + return functions->SetNativeMethodPrefix(this, prefix); + } + + jvmtiError SetNativeMethodPrefixes(jint prefix_count, + char** prefixes) { + return functions->SetNativeMethodPrefixes(this, prefix_count, prefixes); + } + + jvmtiError CreateRawMonitor(const char* name, + jrawMonitorID* monitor_ptr) { + return functions->CreateRawMonitor(this, name, monitor_ptr); + } + + jvmtiError DestroyRawMonitor(jrawMonitorID monitor) { + return functions->DestroyRawMonitor(this, monitor); + } + + jvmtiError RawMonitorEnter(jrawMonitorID monitor) { + return functions->RawMonitorEnter(this, monitor); + } + + jvmtiError RawMonitorExit(jrawMonitorID monitor) { + return functions->RawMonitorExit(this, monitor); + } + + jvmtiError RawMonitorWait(jrawMonitorID monitor, + jlong millis) { + return functions->RawMonitorWait(this, monitor, millis); + } + + jvmtiError RawMonitorNotify(jrawMonitorID monitor) { + return functions->RawMonitorNotify(this, monitor); + } + + jvmtiError RawMonitorNotifyAll(jrawMonitorID monitor) { + return functions->RawMonitorNotifyAll(this, monitor); + } + + jvmtiError SetJNIFunctionTable(const jniNativeInterface* function_table) { + return functions->SetJNIFunctionTable(this, function_table); + } + + jvmtiError GetJNIFunctionTable(jniNativeInterface** function_table) { + return functions->GetJNIFunctionTable(this, function_table); + } + + jvmtiError SetEventCallbacks(const jvmtiEventCallbacks* callbacks, + jint size_of_callbacks) { + return functions->SetEventCallbacks(this, callbacks, size_of_callbacks); + } + + jvmtiError SetEventNotificationMode(jvmtiEventMode mode, + jvmtiEvent event_type, + jthread event_thread, + ...) { + return functions->SetEventNotificationMode(this, mode, event_type, event_thread); + } + + jvmtiError GenerateEvents(jvmtiEvent event_type) { + return functions->GenerateEvents(this, event_type); + } + + jvmtiError GetExtensionFunctions(jint* extension_count_ptr, + jvmtiExtensionFunctionInfo** extensions) { + return functions->GetExtensionFunctions(this, extension_count_ptr, extensions); + } + + jvmtiError GetExtensionEvents(jint* extension_count_ptr, + jvmtiExtensionEventInfo** extensions) { + return functions->GetExtensionEvents(this, extension_count_ptr, extensions); + } + + jvmtiError SetExtensionEventCallback(jint extension_event_index, + jvmtiExtensionEvent callback) { + return functions->SetExtensionEventCallback(this, extension_event_index, callback); + } + + jvmtiError GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) { + return functions->GetPotentialCapabilities(this, capabilities_ptr); + } + + jvmtiError AddCapabilities(const jvmtiCapabilities* capabilities_ptr) { + return functions->AddCapabilities(this, capabilities_ptr); + } + + jvmtiError RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) { + return functions->RelinquishCapabilities(this, capabilities_ptr); + } + + jvmtiError GetCapabilities(jvmtiCapabilities* capabilities_ptr) { + return functions->GetCapabilities(this, capabilities_ptr); + } + + jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { + return functions->GetCurrentThreadCpuTimerInfo(this, info_ptr); + } + + jvmtiError GetCurrentThreadCpuTime(jlong* nanos_ptr) { + return functions->GetCurrentThreadCpuTime(this, nanos_ptr); + } + + jvmtiError GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { + return functions->GetThreadCpuTimerInfo(this, info_ptr); + } + + jvmtiError GetThreadCpuTime(jthread thread, + jlong* nanos_ptr) { + return functions->GetThreadCpuTime(this, thread, nanos_ptr); + } + + jvmtiError GetTimerInfo(jvmtiTimerInfo* info_ptr) { + return functions->GetTimerInfo(this, info_ptr); + } + + jvmtiError GetTime(jlong* nanos_ptr) { + return functions->GetTime(this, nanos_ptr); + } + + jvmtiError GetAvailableProcessors(jint* processor_count_ptr) { + return functions->GetAvailableProcessors(this, processor_count_ptr); + } + + jvmtiError AddToBootstrapClassLoaderSearch(const char* segment) { + return functions->AddToBootstrapClassLoaderSearch(this, segment); + } + + jvmtiError AddToSystemClassLoaderSearch(const char* segment) { + return functions->AddToSystemClassLoaderSearch(this, segment); + } + + jvmtiError GetSystemProperties(jint* count_ptr, + char*** property_ptr) { + return functions->GetSystemProperties(this, count_ptr, property_ptr); + } + + jvmtiError GetSystemProperty(const char* property, + char** value_ptr) { + return functions->GetSystemProperty(this, property, value_ptr); + } + + jvmtiError SetSystemProperty(const char* property, + const char* value) { + return functions->SetSystemProperty(this, property, value); + } + + jvmtiError GetPhase(jvmtiPhase* phase_ptr) { + return functions->GetPhase(this, phase_ptr); + } + + jvmtiError DisposeEnvironment() { + return functions->DisposeEnvironment(this); + } + + jvmtiError SetEnvironmentLocalStorage(const void* data) { + return functions->SetEnvironmentLocalStorage(this, data); + } + + jvmtiError GetEnvironmentLocalStorage(void** data_ptr) { + return functions->GetEnvironmentLocalStorage(this, data_ptr); + } + + jvmtiError GetVersionNumber(jint* version_ptr) { + return functions->GetVersionNumber(this, version_ptr); + } + + jvmtiError GetErrorName(jvmtiError error, + char** name_ptr) { + return functions->GetErrorName(this, error, name_ptr); + } + + jvmtiError SetVerboseFlag(jvmtiVerboseFlag flag, + jboolean value) { + return functions->SetVerboseFlag(this, flag, value); + } + + jvmtiError GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { + return functions->GetJLocationFormat(this, format_ptr); + } + +#endif /* __cplusplus */ +}; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* !_JAVA_JVMTI_H_ */ + diff --git a/arthas-beans/src/main/native/head/jvmticmlr.h b/arthas-beans/src/main/native/head/jvmticmlr.h new file mode 100755 index 000000000..a9c88f36e --- /dev/null +++ b/arthas-beans/src/main/native/head/jvmticmlr.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * This header file defines the data structures sent by the VM + * through the JVMTI CompiledMethodLoad callback function via the + * "void * compile_info" parameter. The memory pointed to by the + * compile_info parameter may not be referenced after returning from + * the CompiledMethodLoad callback. These are VM implementation + * specific data structures that may evolve in future releases. A + * JVMTI agent should interpret a non-NULL compile_info as a pointer + * to a region of memory containing a list of records. In a typical + * usage scenario, a JVMTI agent would cast each record to a + * jvmtiCompiledMethodLoadRecordHeader, a struct that represents + * arbitrary information. This struct contains a kind field to indicate + * the kind of information being passed, and a pointer to the next + * record. If the kind field indicates inlining information, then the + * agent would cast the record to a jvmtiCompiledMethodLoadInlineRecord. + * This record contains an array of PCStackInfo structs, which indicate + * for every pc address what are the methods on the invocation stack. + * The "methods" and "bcis" fields in each PCStackInfo struct specify a + * 1-1 mapping between these inlined methods and their bytecode indices. + * This can be used to derive the proper source lines of the inlined + * methods. + */ + +#ifndef _JVMTI_CMLR_H_ +#define _JVMTI_CMLR_H_ + +enum { + JVMTI_CMLR_MAJOR_VERSION_1 = 0x00000001, + JVMTI_CMLR_MINOR_VERSION_0 = 0x00000000, + + JVMTI_CMLR_MAJOR_VERSION = 0x00000001, + JVMTI_CMLR_MINOR_VERSION = 0x00000000 + + /* + * This comment is for the "JDK import from HotSpot" sanity check: + * version: 1.0.0 + */ +}; + +typedef enum { + JVMTI_CMLR_DUMMY = 1, + JVMTI_CMLR_INLINE_INFO = 2 +} jvmtiCMLRKind; + +/* + * Record that represents arbitrary information passed through JVMTI + * CompiledMethodLoadEvent void pointer. + */ +typedef struct _jvmtiCompiledMethodLoadRecordHeader { + jvmtiCMLRKind kind; /* id for the kind of info passed in the record */ + jint majorinfoversion; /* major and minor info version values. Init'ed */ + jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */ + + struct _jvmtiCompiledMethodLoadRecordHeader* next; +} jvmtiCompiledMethodLoadRecordHeader; + +/* + * Record that gives information about the methods on the compile-time + * stack at a specific pc address of a compiled method. Each element in + * the methods array maps to same element in the bcis array. + */ +typedef struct _PCStackInfo { + void* pc; /* the pc address for this compiled method */ + jint numstackframes; /* number of methods on the stack */ + jmethodID* methods; /* array of numstackframes method ids */ + jint* bcis; /* array of numstackframes bytecode indices */ +} PCStackInfo; + +/* + * Record that contains inlining information for each pc address of + * an nmethod. + */ +typedef struct _jvmtiCompiledMethodLoadInlineRecord { + jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */ + jint numpcs; /* number of pc descriptors in this nmethod */ + PCStackInfo* pcinfo; /* array of numpcs pc descriptors */ +} jvmtiCompiledMethodLoadInlineRecord; + +/* + * Dummy record used to test that we can pass records with different + * information through the void pointer provided that they can be cast + * to a jvmtiCompiledMethodLoadRecordHeader. + */ + +typedef struct _jvmtiCompiledMethodLoadDummyRecord { + jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */ + char message[50]; +} jvmtiCompiledMethodLoadDummyRecord; + +#endif diff --git a/arthas-beans/src/main/native/head/linux/jawt_md.h b/arthas-beans/src/main/native/head/linux/jawt_md.h new file mode 100644 index 000000000..825142ca8 --- /dev/null +++ b/arthas-beans/src/main/native/head/linux/jawt_md.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JAWT_MD_H_ +#define _JAVASOFT_JAWT_MD_H_ + +#include +#include +#include +#include "jawt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * X11-specific declarations for AWT native interface. + * See notes in jawt.h for an example of use. + */ +typedef struct jawt_X11DrawingSurfaceInfo { + Drawable drawable; + Display* display; + VisualID visualID; + Colormap colormapID; + int depth; + /* + * Since 1.4 + * Returns a pixel value from a set of RGB values. + * This is useful for paletted color (256 color) modes. + */ + int (JNICALL *GetAWTColor)(JAWT_DrawingSurface* ds, + int r, int g, int b); +} JAWT_X11DrawingSurfaceInfo; + +#ifdef __cplusplus +} +#endif + +#endif /* !_JAVASOFT_JAWT_MD_H_ */ diff --git a/arthas-beans/src/main/native/head/linux/jni_md.h b/arthas-beans/src/main/native/head/linux/jni_md.h new file mode 100644 index 000000000..ff30a32c3 --- /dev/null +++ b/arthas-beans/src/main/native/head/linux/jni_md.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JNI_MD_H_ +#define _JAVASOFT_JNI_MD_H_ + +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility) + #define JNIEXPORT __attribute__((visibility("default"))) + #define JNIIMPORT __attribute__((visibility("default"))) +#else + #define JNIEXPORT + #define JNIIMPORT +#endif + +#define JNICALL + +typedef int jint; +#ifdef _LP64 /* 64-bit Solaris */ +typedef long jlong; +#else +typedef long long jlong; +#endif + +typedef signed char jbyte; + +#endif /* !_JAVASOFT_JNI_MD_H_ */ diff --git a/arthas-beans/src/main/native/head/macos/jawt_md.h b/arthas-beans/src/main/native/head/macos/jawt_md.h new file mode 100644 index 000000000..d803a0f7f --- /dev/null +++ b/arthas-beans/src/main/native/head/macos/jawt_md.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JAWT_MD_H_ +#define _JAVASOFT_JAWT_MD_H_ + +#include "jawt.h" + +#ifdef __OBJC__ +#import +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Mac OS X specific declarations for AWT native interface. + * See notes in jawt.h for an example of use. + */ + +/* + * When calling JAWT_GetAWT with a JAWT version less than 1.7, you must pass this + * flag or you will not be able to get a valid drawing surface and JAWT_GetAWT will + * return false. This is to maintain compatibility with applications that used the + * interface with Java 6 which had multiple rendering models. This flag is not necessary + * when JAWT version 1.7 or greater is used as this is the only supported rendering mode. + * + * Example: + * JAWT awt; + * awt.version = JAWT_VERSION_1_4 | JAWT_MACOSX_USE_CALAYER; + * jboolean success = JAWT_GetAWT(env, &awt); + */ +#define JAWT_MACOSX_USE_CALAYER 0x80000000 + +/* + * When the native Cocoa toolkit is in use, the pointer stored in + * JAWT_DrawingSurfaceInfo->platformInfo points to a NSObject that conforms to the + * JAWT_SurfaceLayers protocol. Setting the layer property of this object will cause the + * specified layer to be overlaid on the Components rectangle. If the window the + * Component belongs to has a CALayer attached to it, this layer will be accessible via + * the windowLayer property. + */ +#ifdef __OBJC__ +@protocol JAWT_SurfaceLayers +@property (readwrite, retain) CALayer *layer; +@property (readonly) CALayer *windowLayer; +@end +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !_JAVASOFT_JAWT_MD_H_ */ diff --git a/arthas-beans/src/main/native/head/macos/jni_md.h b/arthas-beans/src/main/native/head/macos/jni_md.h new file mode 100644 index 000000000..d2b83307f --- /dev/null +++ b/arthas-beans/src/main/native/head/macos/jni_md.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JNI_MD_H_ +#define _JAVASOFT_JNI_MD_H_ + +#define JNIEXPORT __attribute__((visibility("default"))) +#define JNIIMPORT __attribute__((visibility("default"))) +#define JNICALL + +typedef int jint; +#ifdef _LP64 /* 64-bit */ +typedef long jlong; +#else +typedef long long jlong; +#endif + +typedef signed char jbyte; + +#endif /* !_JAVASOFT_JNI_MD_H_ */ diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgeCallbacks.h b/arthas-beans/src/main/native/head/windows/AccessBridgeCallbacks.h new file mode 100755 index 000000000..df5035b84 --- /dev/null +++ b/arthas-beans/src/main/native/head/windows/AccessBridgeCallbacks.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * AccessBridgeCallbacks.h 1.17 05/03/21 + */ + +/* + * Header file defining callback typedefs for Windows routines + * which are called from Java (responding to events, etc.). + */ + +#ifndef __AccessBridgeCallbacks_H__ +#define __AccessBridgeCallbacks_H__ + +#include +#include "AccessBridgePackages.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*AccessBridge_PropertyChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + wchar_t *property, wchar_t *oldValue, wchar_t *newValue); + +typedef void (*AccessBridge_JavaShutdownFP) (long vmID); +typedef void (*AccessBridge_JavaShutdownFP) (long vmID); + +typedef void (*AccessBridge_FocusGainedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_FocusLostFP) (long vmID, JOBJECT64 event, JOBJECT64 source); + +typedef void (*AccessBridge_CaretUpdateFP) (long vmID, JOBJECT64 event, JOBJECT64 source); + +typedef void (*AccessBridge_MouseClickedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_MouseEnteredFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_MouseExitedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_MousePressedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_MouseReleasedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); + +typedef void (*AccessBridge_MenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_MenuDeselectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_MenuSelectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_PopupMenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_PopupMenuWillBecomeInvisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_PopupMenuWillBecomeVisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source); + +typedef void (*AccessBridge_PropertyNameChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + wchar_t *oldName, wchar_t *newName); +typedef void (*AccessBridge_PropertyDescriptionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + wchar_t *oldDescription, wchar_t *newDescription); +typedef void (*AccessBridge_PropertyStateChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + wchar_t *oldState, wchar_t *newState); +typedef void (*AccessBridge_PropertyValueChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + wchar_t *oldValue, wchar_t *newValue); +typedef void (*AccessBridge_PropertySelectionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_PropertyTextChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_PropertyCaretChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + int oldPosition, int newPosition); +typedef void (*AccessBridge_PropertyVisibleDataChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source); +typedef void (*AccessBridge_PropertyChildChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source, + JOBJECT64 oldChild, JOBJECT64 newChild); +typedef void (*AccessBridge_PropertyActiveDescendentChangeFP) (long vmID, JOBJECT64 event, + JOBJECT64 source, + JOBJECT64 oldActiveDescendent, + JOBJECT64 newActiveDescendent); + +typedef void (*AccessBridge_PropertyTableModelChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 src, + wchar_t *oldValue, wchar_t *newValue); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.c b/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.c new file mode 100755 index 000000000..368664818 --- /dev/null +++ b/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.c @@ -0,0 +1,1131 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * @(#)AccessBridgeCalls.c 1.25 05/08/22 + */ + +/* + * Wrapper functions around calls to the AccessBridge DLL + */ + + +#include +#include + + +//#define ACCESSBRIDGE_32 +//#define ACCESSBRIDGE_64 + +#include "AccessBridgeCalls.h" +#include "AccessBridgeDebug.h" + +#ifdef __cplusplus +extern "C" { +#endif + + HINSTANCE theAccessBridgeInstance; + AccessBridgeFPs theAccessBridge; + + BOOL theAccessBridgeInitializedFlag = FALSE; + +#define LOAD_FP(result, type, name) \ + PrintDebugString("LOAD_FP loading: %s ...", name); \ + if ((theAccessBridge.result = \ + (type) GetProcAddress(theAccessBridgeInstance, name)) == (type) 0) { \ + PrintDebugString("LOAD_FP failed: %s", name); \ + return FALSE; \ + } + + BOOL initializeAccessBridge() { + +#ifdef ACCESSBRIDGE_ARCH_32 // For 32bit AT new bridge + theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-32"); +#else +#ifdef ACCESSBRIDGE_ARCH_64 // For 64bit AT new bridge + theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-64"); +#else // legacy + theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE"); +#endif +#endif + if (theAccessBridgeInstance != 0) { + LOAD_FP(Windows_run, Windows_runFP, "Windows_run"); + + LOAD_FP(SetJavaShutdown, SetJavaShutdownFP, "setJavaShutdownFP"); + LOAD_FP(SetFocusGained, SetFocusGainedFP, "setFocusGainedFP"); + LOAD_FP(SetFocusLost, SetFocusLostFP, "setFocusLostFP"); + + LOAD_FP(SetCaretUpdate, SetCaretUpdateFP, "setCaretUpdateFP"); + + LOAD_FP(SetMouseClicked, SetMouseClickedFP, "setMouseClickedFP"); + LOAD_FP(SetMouseEntered, SetMouseEnteredFP, "setMouseEnteredFP"); + LOAD_FP(SetMouseExited, SetMouseExitedFP, "setMouseExitedFP"); + LOAD_FP(SetMousePressed, SetMousePressedFP, "setMousePressedFP"); + LOAD_FP(SetMouseReleased, SetMouseReleasedFP, "setMouseReleasedFP"); + + LOAD_FP(SetMenuCanceled, SetMenuCanceledFP, "setMenuCanceledFP"); + LOAD_FP(SetMenuDeselected, SetMenuDeselectedFP, "setMenuDeselectedFP"); + LOAD_FP(SetMenuSelected, SetMenuSelectedFP, "setMenuSelectedFP"); + LOAD_FP(SetPopupMenuCanceled, SetPopupMenuCanceledFP, "setPopupMenuCanceledFP"); + LOAD_FP(SetPopupMenuWillBecomeInvisible, SetPopupMenuWillBecomeInvisibleFP, "setPopupMenuWillBecomeInvisibleFP"); + LOAD_FP(SetPopupMenuWillBecomeVisible, SetPopupMenuWillBecomeVisibleFP, "setPopupMenuWillBecomeVisibleFP"); + + LOAD_FP(SetPropertyNameChange, SetPropertyNameChangeFP, "setPropertyNameChangeFP"); + LOAD_FP(SetPropertyDescriptionChange, SetPropertyDescriptionChangeFP, "setPropertyDescriptionChangeFP"); + LOAD_FP(SetPropertyStateChange, SetPropertyStateChangeFP, "setPropertyStateChangeFP"); + LOAD_FP(SetPropertyValueChange, SetPropertyValueChangeFP, "setPropertyValueChangeFP"); + LOAD_FP(SetPropertySelectionChange, SetPropertySelectionChangeFP, "setPropertySelectionChangeFP"); + LOAD_FP(SetPropertyTextChange, SetPropertyTextChangeFP, "setPropertyTextChangeFP"); + LOAD_FP(SetPropertyCaretChange, SetPropertyCaretChangeFP, "setPropertyCaretChangeFP"); + LOAD_FP(SetPropertyVisibleDataChange, SetPropertyVisibleDataChangeFP, "setPropertyVisibleDataChangeFP"); + LOAD_FP(SetPropertyChildChange, SetPropertyChildChangeFP, "setPropertyChildChangeFP"); + LOAD_FP(SetPropertyActiveDescendentChange, SetPropertyActiveDescendentChangeFP, "setPropertyActiveDescendentChangeFP"); + + LOAD_FP(SetPropertyTableModelChange, SetPropertyTableModelChangeFP, "setPropertyTableModelChangeFP"); + + LOAD_FP(ReleaseJavaObject, ReleaseJavaObjectFP, "releaseJavaObject"); + LOAD_FP(GetVersionInfo, GetVersionInfoFP, "getVersionInfo"); + + LOAD_FP(IsJavaWindow, IsJavaWindowFP, "isJavaWindow"); + LOAD_FP(IsSameObject, IsSameObjectFP, "isSameObject"); + LOAD_FP(GetAccessibleContextFromHWND, GetAccessibleContextFromHWNDFP, "getAccessibleContextFromHWND"); + LOAD_FP(getHWNDFromAccessibleContext, getHWNDFromAccessibleContextFP, "getHWNDFromAccessibleContext"); + + LOAD_FP(GetAccessibleContextAt, GetAccessibleContextAtFP, "getAccessibleContextAt"); + LOAD_FP(GetAccessibleContextWithFocus, GetAccessibleContextWithFocusFP, "getAccessibleContextWithFocus"); + LOAD_FP(GetAccessibleContextInfo, GetAccessibleContextInfoFP, "getAccessibleContextInfo"); + LOAD_FP(GetAccessibleChildFromContext, GetAccessibleChildFromContextFP, "getAccessibleChildFromContext"); + LOAD_FP(GetAccessibleParentFromContext, GetAccessibleParentFromContextFP, "getAccessibleParentFromContext"); + + /* begin AccessibleTable */ + LOAD_FP(getAccessibleTableInfo, getAccessibleTableInfoFP, "getAccessibleTableInfo"); + LOAD_FP(getAccessibleTableCellInfo, getAccessibleTableCellInfoFP, "getAccessibleTableCellInfo"); + + LOAD_FP(getAccessibleTableRowHeader, getAccessibleTableRowHeaderFP, "getAccessibleTableRowHeader"); + LOAD_FP(getAccessibleTableColumnHeader, getAccessibleTableColumnHeaderFP, "getAccessibleTableColumnHeader"); + + LOAD_FP(getAccessibleTableRowDescription, getAccessibleTableRowDescriptionFP, "getAccessibleTableRowDescription"); + LOAD_FP(getAccessibleTableColumnDescription, getAccessibleTableColumnDescriptionFP, "getAccessibleTableColumnDescription"); + + LOAD_FP(getAccessibleTableRowSelectionCount, getAccessibleTableRowSelectionCountFP, + "getAccessibleTableRowSelectionCount"); + LOAD_FP(isAccessibleTableRowSelected, isAccessibleTableRowSelectedFP, + "isAccessibleTableRowSelected"); + LOAD_FP(getAccessibleTableRowSelections, getAccessibleTableRowSelectionsFP, + "getAccessibleTableRowSelections"); + + LOAD_FP(getAccessibleTableColumnSelectionCount, getAccessibleTableColumnSelectionCountFP, + "getAccessibleTableColumnSelectionCount"); + LOAD_FP(isAccessibleTableColumnSelected, isAccessibleTableColumnSelectedFP, + "isAccessibleTableColumnSelected"); + LOAD_FP(getAccessibleTableColumnSelections, getAccessibleTableColumnSelectionsFP, + "getAccessibleTableColumnSelections"); + + LOAD_FP(getAccessibleTableRow, getAccessibleTableRowFP, + "getAccessibleTableRow"); + LOAD_FP(getAccessibleTableColumn, getAccessibleTableColumnFP, + "getAccessibleTableColumn"); + LOAD_FP(getAccessibleTableIndex, getAccessibleTableIndexFP, + "getAccessibleTableIndex"); + + /* end AccessibleTable */ + + /* AccessibleRelationSet */ + LOAD_FP(getAccessibleRelationSet, getAccessibleRelationSetFP, "getAccessibleRelationSet"); + + /* AccessibleHypertext */ + LOAD_FP(getAccessibleHypertext, getAccessibleHypertextFP, "getAccessibleHypertext"); + LOAD_FP(activateAccessibleHyperlink, activateAccessibleHyperlinkFP, "activateAccessibleHyperlink"); + LOAD_FP(getAccessibleHyperlinkCount, getAccessibleHyperlinkCountFP, "getAccessibleHyperlinkCount"); + LOAD_FP(getAccessibleHypertextExt, getAccessibleHypertextExtFP, "getAccessibleHypertextExt"); + LOAD_FP(getAccessibleHypertextLinkIndex, getAccessibleHypertextLinkIndexFP, "getAccessibleHypertextLinkIndex"); + LOAD_FP(getAccessibleHyperlink, getAccessibleHyperlinkFP, "getAccessibleHyperlink"); + + /* Accessible KeyBinding, Icon and Action */ + LOAD_FP(getAccessibleKeyBindings, getAccessibleKeyBindingsFP, "getAccessibleKeyBindings"); + LOAD_FP(getAccessibleIcons, getAccessibleIconsFP, "getAccessibleIcons"); + LOAD_FP(getAccessibleActions, getAccessibleActionsFP, "getAccessibleActions"); + LOAD_FP(doAccessibleActions, doAccessibleActionsFP, "doAccessibleActions"); + + /* AccessibleText */ + LOAD_FP(GetAccessibleTextInfo, GetAccessibleTextInfoFP, "getAccessibleTextInfo"); + LOAD_FP(GetAccessibleTextItems, GetAccessibleTextItemsFP, "getAccessibleTextItems"); + LOAD_FP(GetAccessibleTextSelectionInfo, GetAccessibleTextSelectionInfoFP, "getAccessibleTextSelectionInfo"); + LOAD_FP(GetAccessibleTextAttributes, GetAccessibleTextAttributesFP, "getAccessibleTextAttributes"); + LOAD_FP(GetAccessibleTextRect, GetAccessibleTextRectFP, "getAccessibleTextRect"); + LOAD_FP(GetAccessibleTextLineBounds, GetAccessibleTextLineBoundsFP, "getAccessibleTextLineBounds"); + LOAD_FP(GetAccessibleTextRange, GetAccessibleTextRangeFP, "getAccessibleTextRange"); + + LOAD_FP(GetCurrentAccessibleValueFromContext, GetCurrentAccessibleValueFromContextFP, "getCurrentAccessibleValueFromContext"); + LOAD_FP(GetMaximumAccessibleValueFromContext, GetMaximumAccessibleValueFromContextFP, "getMaximumAccessibleValueFromContext"); + LOAD_FP(GetMinimumAccessibleValueFromContext, GetMinimumAccessibleValueFromContextFP, "getMinimumAccessibleValueFromContext"); + + LOAD_FP(AddAccessibleSelectionFromContext, AddAccessibleSelectionFromContextFP, "addAccessibleSelectionFromContext"); + LOAD_FP(ClearAccessibleSelectionFromContext, ClearAccessibleSelectionFromContextFP, "clearAccessibleSelectionFromContext"); + LOAD_FP(GetAccessibleSelectionFromContext, GetAccessibleSelectionFromContextFP, "getAccessibleSelectionFromContext"); + LOAD_FP(GetAccessibleSelectionCountFromContext, GetAccessibleSelectionCountFromContextFP, "getAccessibleSelectionCountFromContext"); + LOAD_FP(IsAccessibleChildSelectedFromContext, IsAccessibleChildSelectedFromContextFP, "isAccessibleChildSelectedFromContext"); + LOAD_FP(RemoveAccessibleSelectionFromContext, RemoveAccessibleSelectionFromContextFP, "removeAccessibleSelectionFromContext"); + LOAD_FP(SelectAllAccessibleSelectionFromContext, SelectAllAccessibleSelectionFromContextFP, "selectAllAccessibleSelectionFromContext"); + + LOAD_FP(setTextContents, setTextContentsFP, "setTextContents"); + LOAD_FP(getParentWithRole, getParentWithRoleFP, "getParentWithRole"); + LOAD_FP(getTopLevelObject, getTopLevelObjectFP, "getTopLevelObject"); + LOAD_FP(getParentWithRoleElseRoot, getParentWithRoleElseRootFP, "getParentWithRoleElseRoot"); + LOAD_FP(getObjectDepth, getObjectDepthFP, "getObjectDepth"); + LOAD_FP(getActiveDescendent, getActiveDescendentFP, "getActiveDescendent"); + + // additional methods for Teton + LOAD_FP(getVirtualAccessibleName, getVirtualAccessibleNameFP, "getVirtualAccessibleName"); + LOAD_FP(requestFocus, requestFocusFP, "requestFocus"); + LOAD_FP(selectTextRange, selectTextRangeFP, "selectTextRange"); + LOAD_FP(getTextAttributesInRange, getTextAttributesInRangeFP, "getTextAttributesInRange"); + LOAD_FP(getVisibleChildrenCount, getVisibleChildrenCountFP, "getVisibleChildrenCount"); + LOAD_FP(getVisibleChildren, getVisibleChildrenFP, "getVisibleChildren"); + LOAD_FP(setCaretPosition, setCaretPositionFP, "setCaretPosition"); + LOAD_FP(getCaretLocation, getCaretLocationFP, "getCaretLocation"); + + LOAD_FP(getEventsWaiting, getEventsWaitingFP, "getEventsWaiting"); + + theAccessBridge.Windows_run(); + + theAccessBridgeInitializedFlag = TRUE; + PrintDebugString("theAccessBridgeInitializedFlag = TRUE"); + return TRUE; + } else { + return FALSE; + } + } + + + BOOL shutdownAccessBridge() { + BOOL result; + DWORD error; + theAccessBridgeInitializedFlag = FALSE; + if (theAccessBridgeInstance != (HANDLE) 0) { + result = FreeLibrary(theAccessBridgeInstance); + if (result != TRUE) { + error = GetLastError(); + } + return TRUE; + } + return FALSE; + } + + + void SetJavaShutdown(AccessBridge_JavaShutdownFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetJavaShutdown(fp); + } + } + + void SetFocusGained(AccessBridge_FocusGainedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetFocusGained(fp); + } + } + + void SetFocusLost(AccessBridge_FocusLostFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetFocusLost(fp); + } + } + + + void SetCaretUpdate(AccessBridge_CaretUpdateFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetCaretUpdate(fp); + } + } + + + void SetMouseClicked(AccessBridge_MouseClickedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMouseClicked(fp); + } + } + + void SetMouseEntered(AccessBridge_MouseEnteredFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMouseEntered(fp); + } + } + + void SetMouseExited(AccessBridge_MouseExitedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMouseExited(fp); + } + } + + void SetMousePressed(AccessBridge_MousePressedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMousePressed(fp); + } + } + + void SetMouseReleased(AccessBridge_MouseReleasedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMouseReleased(fp); + } + } + + + void SetMenuCanceled(AccessBridge_MenuCanceledFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMenuCanceled(fp); + } + } + + void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMenuDeselected(fp); + } + } + + void SetMenuSelected(AccessBridge_MenuSelectedFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetMenuSelected(fp); + } + } + + void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPopupMenuCanceled(fp); + } + } + + void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPopupMenuWillBecomeInvisible(fp); + } + } + + void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPopupMenuWillBecomeVisible(fp); + } + } + + + void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyNameChange(fp); + } + } + + void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyDescriptionChange(fp); + } + } + + void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyStateChange(fp); + } + } + + void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyValueChange(fp); + } + } + + void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertySelectionChange(fp); + } + } + + void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyTextChange(fp); + } + } + + void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyCaretChange(fp); + } + } + + void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyVisibleDataChange(fp); + } + } + + void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyChildChange(fp); + } + } + + void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyActiveDescendentChange(fp); + } + } + + void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SetPropertyTableModelChange(fp); + } + } + + /** + * General routines + */ + void ReleaseJavaObject(long vmID, Java_Object object) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.ReleaseJavaObject(vmID, object); + } + } + + BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetVersionInfo(vmID, info); + } + return FALSE; + } + + + /** + * Window routines + */ + BOOL IsJavaWindow(HWND window) { + if (theAccessBridgeInitializedFlag == TRUE) { + BOOL ret ; + ret = theAccessBridge.IsJavaWindow(window); + return ret ; + + } + return FALSE; + } + + + /** + * Returns the virtual machine ID and AccessibleContext for a top-level window + */ + BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleContextFromHWND(target, vmID, ac); + } + return FALSE; + } + + /** + * Returns the HWND from the AccessibleContext of a top-level window. Returns 0 + * on error or if the AccessibleContext does not refer to a top-level window. + */ + HWND getHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getHWNDFromAccessibleContext(vmID, accesibleContext); + } + return (HWND)0; + } + + /** + * returns whether two objects are the same + */ + BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.IsSameObject(vmID, obj1, obj2); + } + return FALSE; + } + + /** + * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and + * be editable. The maximum text length is MAX_STRING_SIZE - 1. + * Returns whether successful + */ + BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.setTextContents(vmID, accessibleContext, text); + } + return FALSE; + } + + /** + * Returns the Accessible Context with the specified role that is the + * ancestor of a given object. The role is one of the role strings + * defined in AccessBridgePackages.h + * If there is no ancestor object that has the specified role, + * returns (AccessibleContext)0. + */ + AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext, + const wchar_t *role) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getParentWithRole(vmID, accessibleContext, role); + } + return (AccessibleContext)0; + } + + /** + * Returns the Accessible Context with the specified role that is the + * ancestor of a given object. The role is one of the role strings + * defined in AccessBridgePackages.h. If an object with the specified + * role does not exist, returns the top level object for the Java Window. + * Returns (AccessibleContext)0 on error. + */ + AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext, + const wchar_t *role) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getParentWithRoleElseRoot(vmID, accessibleContext, role); + } + return (AccessibleContext)0; + } + + /** + * Returns the Accessible Context for the top level object in + * a Java Window. This is same Accessible Context that is obtained + * from GetAccessibleContextFromHWND for that window. Returns + * (AccessibleContext)0 on error. + */ + AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getTopLevelObject(vmID, accessibleContext); + } + return (AccessibleContext)0; + } + + /** + * Returns how deep in the object hierarchy a given object is. + * The top most object in the object hierarchy has an object depth of 0. + * Returns -1 on error. + */ + int getObjectDepth (const long vmID, const AccessibleContext accessibleContext) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getObjectDepth(vmID, accessibleContext); + } + return -1; + } + + /** + * Returns the Accessible Context of the current ActiveDescendent of an object. + * This method assumes the ActiveDescendent is the component that is currently + * selected in a container object. + * Returns (AccessibleContext)0 on error or if there is no selection. + */ + AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getActiveDescendent(vmID, accessibleContext); + } + return (AccessibleContext)0; + } + + + /** + * Accessible Context routines + */ + BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent, + jint x, jint y, AccessibleContext *ac) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleContextAt(vmID, acParent, x, y, ac); + } + return FALSE; + } + + BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleContextWithFocus(window, vmID, ac); + } + return FALSE; + } + + BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleContextInfo(vmID, ac, info); + } + return FALSE; + } + + AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleChildFromContext(vmID, ac, index); + } + return (AccessibleContext) 0; + } + + AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleParentFromContext(vmID, ac); + } + return (AccessibleContext) 0; + } + + /* begin AccessibleTable routines */ + + /* + * get information about an AccessibleTable + */ + BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableInfo(vmID, acParent, tableInfo); + } + return FALSE; + } + + /* + * get information about an AccessibleTable cell + */ + BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable, + jint row, jint column, AccessibleTableCellInfo *tableCellInfo) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableCellInfo(vmID, accessibleTable, row, column, tableCellInfo); + } + return FALSE; + } + + /* + * get information about an AccessibleTable row header + */ + BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableRowHeader(vmID, acParent, tableInfo); + } + return FALSE; + } + + /* + * get information about an AccessibleTable column header + */ + BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableColumnHeader(vmID, acParent, tableInfo); + } + return FALSE; + } + + /* + * return a description of an AccessibleTable row header + */ + AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableRowDescription(vmID, acParent, row); + } + return (AccessibleContext)0; + } + + /* + * return a description of an AccessibleTable column header + */ + AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableColumnDescription(vmID, acParent, column); + } + return (AccessibleContext)0; + } + + /* + * return the number of rows selected in an AccessibleTable + */ + jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableRowSelectionCount(vmID, table); + } + return -1; + } + + /* + * return whether a row is selected in an AccessibleTable + */ + BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.isAccessibleTableRowSelected(vmID, table, row); + } + return FALSE; + } + + /* + * get an array of selected rows in an AccessibleTable + */ + BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableRowSelections(vmID, table, count, selections); + } + return FALSE; + } + + /* + * return the number of columns selected in an AccessibleTable + */ + jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableColumnSelectionCount(vmID, table); + } + return -1; + } + + /* + * return whether a column is selected in an AccessibleTable + */ + BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.isAccessibleTableColumnSelected(vmID, table, column); + } + return FALSE; + } + + /* + * get an array of columns selected in an AccessibleTable + */ + BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableColumnSelections(vmID, table, count, selections); + } + return FALSE; + } + + /* + * return the row number for a cell at a given index + */ + jint + getAccessibleTableRow(long vmID, AccessibleTable table, jint index) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableRow(vmID, table, index); + } + return -1; + } + + /* + * return the column number for a cell at a given index + */ + jint + getAccessibleTableColumn(long vmID, AccessibleTable table, jint index) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableColumn(vmID, table, index); + } + return -1; + } + + /* + * return the index of a cell at a given row and column + */ + jint + getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleTableIndex(vmID, table, row, column); + } + return -1; + } + + /* end AccessibleTable routines */ + + + /** + * Accessible Text routines + */ + BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextInfo(vmID, at, textInfo, x, y); + } + return FALSE; + } + + BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextItems(vmID, at, textItems, index); + } + return FALSE; + } + + BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextSelectionInfo(vmID, at, textSelection); + } + return FALSE; + } + + BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextAttributes(vmID, at, index, attributes); + } + return FALSE; + } + + BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextRect(vmID, at, rectInfo, index); + } + return FALSE; + } + + BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextLineBounds(vmID, at, index, startIndex, endIndex); + } + return FALSE; + } + + BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleTextRange(vmID, at, start, end, text, len); + } + return FALSE; + } + + /** + * AccessibleRelationSet routines + */ + BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext, + AccessibleRelationSetInfo *relationSetInfo) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleRelationSet(vmID, accessibleContext, relationSetInfo); + } + return FALSE; + } + + /** + * AccessibleHypertext routines + */ + + // Gets AccessibleHypertext for an AccessibleContext + BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext, + AccessibleHypertextInfo *hypertextInfo) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleHypertext(vmID, accessibleContext, hypertextInfo); + } + return FALSE; + } + + // Activates an AccessibleHyperlink for an AccessibleContext + BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext, + AccessibleHyperlink accessibleHyperlink) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.activateAccessibleHyperlink(vmID, accessibleContext, accessibleHyperlink); + } + return FALSE; + } + + /* + * Returns the number of hyperlinks in a component + * Maps to AccessibleHypertext.getLinkCount. + * Returns -1 on error. + */ + jint getAccessibleHyperlinkCount(const long vmID, + const AccessibleContext accessibleContext) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleHyperlinkCount(vmID, accessibleContext); + } + return -1; + } + + /* + * This method is used to iterate through the hyperlinks in a component. It + * returns hypertext information for a component starting at hyperlink index + * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will + * be returned for each call to this method. + * returns FALSE on error. + */ + BOOL getAccessibleHypertextExt(const long vmID, + const AccessibleContext accessibleContext, + const jint nStartIndex, + /* OUT */ AccessibleHypertextInfo *hypertextInfo) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleHypertextExt(vmID, + accessibleContext, + nStartIndex, + hypertextInfo); + } + return FALSE; + } + + /* + * Returns the index into an array of hyperlinks that is associated with + * a character index in document; + * Maps to AccessibleHypertext.getLinkIndex. + * Returns -1 on error. + */ + jint getAccessibleHypertextLinkIndex(const long vmID, + const AccessibleHypertext hypertext, + const jint nIndex) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleHypertextLinkIndex(vmID, + hypertext, + nIndex); + } + return -1; + } + + /* + * Returns the nth hyperlink in a document. + * Maps to AccessibleHypertext.getLink. + * Returns -1 on error + */ + BOOL getAccessibleHyperlink(const long vmID, + const AccessibleHypertext hypertext, + const jint nIndex, + /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo) { + + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleHyperlink(vmID, + hypertext, + nIndex, + hyperlinkInfo); + } + return FALSE; + } + + + /* Accessible KeyBindings, Icons and Actions */ + BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext, + AccessibleKeyBindings *keyBindings) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleKeyBindings(vmID, accessibleContext, keyBindings); + } + return FALSE; + } + + BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext, + AccessibleIcons *icons) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleIcons(vmID, accessibleContext, icons); + } + return FALSE; + } + + BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext, + AccessibleActions *actions) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getAccessibleActions(vmID, accessibleContext, actions); + } + return FALSE; + } + + BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext, + AccessibleActionsToDo *actionsToDo, jint *failure) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.doAccessibleActions(vmID, accessibleContext, actionsToDo, failure); + } + return FALSE; + } + + /** + * Accessible Value routines + */ + BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetCurrentAccessibleValueFromContext(vmID, av, value, len); + } + return FALSE; + } + + BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetMaximumAccessibleValueFromContext(vmID, av, value, len); + } + return FALSE; + } + + BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetMinimumAccessibleValueFromContext(vmID, av, value, len); + } + return FALSE; + } + + + /** + * Accessible Selection routines + */ + void addAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.AddAccessibleSelectionFromContext(vmID, as, i); + } + } + + void clearAccessibleSelectionFromContext(long vmID, AccessibleSelection as) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.ClearAccessibleSelectionFromContext(vmID, as); + } + } + + JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleSelectionFromContext(vmID, as, i); + } + return (JOBJECT64) 0; + } + + int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.GetAccessibleSelectionCountFromContext(vmID, as); + } + return -1; + } + + BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.IsAccessibleChildSelectedFromContext(vmID, as, i); + } + return FALSE; + } + + void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.RemoveAccessibleSelectionFromContext(vmID, as, i); + } + } + + void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as) { + if (theAccessBridgeInitializedFlag == TRUE) { + theAccessBridge.SelectAllAccessibleSelectionFromContext(vmID, as); + } + } + + /** + * Additional methods for Teton + */ + + /** + * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns + * whether successful. + * + * Bug ID 4916682 - Implement JAWS AccessibleName policy + */ + BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext, + wchar_t *name, int len) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getVirtualAccessibleName(vmID, accessibleContext, name, len); + } + return FALSE; + } + + /** + * Request focus for a component. Returns whether successful; + * + * Bug ID 4944757 - requestFocus method needed + */ + BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.requestFocus(vmID, accessibleContext); + } + return FALSE; + } + + /** + * Selects text between two indices. Selection includes the text at the start index + * and the text at the end index. Returns whether successful; + * + * Bug ID 4944758 - selectTextRange method needed + */ + BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext, + const int startIndex, const int endIndex) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.selectTextRange(vmID, accessibleContext, startIndex, endIndex); + } + return FALSE; + } + + /** + * Get text attributes between two indices. The attribute list includes the text at the + * start index and the text at the end index. Returns whether successful; + * + * Bug ID 4944761 - getTextAttributes between two indices method needed + */ + BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext, + const int startIndex, const int endIndex, + AccessibleTextAttributesInfo *attributes, short *len) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getTextAttributesInRange(vmID, accessibleContext, startIndex, + endIndex, attributes, len); + } + return FALSE; + } + + /** + * Returns the number of visible children of a component. Returns -1 on error. + * + * Bug ID 4944762- getVisibleChildren for list-like components needed + */ + int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getVisibleChildrenCount(vmID, accessibleContext); + } + return FALSE; + } + + /** + * Gets the visible children of an AccessibleContext. Returns whether successful; + * + * Bug ID 4944762- getVisibleChildren for list-like components needed + */ + BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext, + const int startIndex, VisibleChildrenInfo *visibleChildrenInfo) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getVisibleChildren(vmID, accessibleContext, startIndex, + visibleChildrenInfo); + } + return FALSE; + } + + /** + * Set the caret to a text position. Returns whether successful; + * + * Bug ID 4944770 - setCaretPosition method needed + */ + BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext, + const int position) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.setCaretPosition(vmID, accessibleContext, position); + } + return FALSE; + } + + /** + * Gets the text caret location + */ + BOOL getCaretLocation(long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index) { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getCaretLocation(vmID, ac, rectInfo, index); + } + return FALSE; + } + + /** + * Gets the number of events waiting to fire + */ + int getEventsWaiting() { + if (theAccessBridgeInitializedFlag == TRUE) { + return theAccessBridge.getEventsWaiting(); + } + return FALSE; + } + +#ifdef __cplusplus +} +#endif diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.h b/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.h new file mode 100755 index 000000000..ad0074009 --- /dev/null +++ b/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.h @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * Wrapper functions around calls to the AccessBridge DLL + */ + +#include +#include +#include "AccessBridgeCallbacks.h" +#include "AccessBridgePackages.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define null NULL + + typedef JOBJECT64 AccessibleContext; + typedef JOBJECT64 AccessibleText; + typedef JOBJECT64 AccessibleValue; + typedef JOBJECT64 AccessibleSelection; + typedef JOBJECT64 Java_Object; + typedef JOBJECT64 PropertyChangeEvent; + typedef JOBJECT64 FocusEvent; + typedef JOBJECT64 CaretEvent; + typedef JOBJECT64 MouseEvent; + typedef JOBJECT64 MenuEvent; + typedef JOBJECT64 AccessibleTable; + typedef JOBJECT64 AccessibleHyperlink; + typedef JOBJECT64 AccessibleHypertext; + + + typedef void (*Windows_runFP) (); + + typedef void (*SetPropertyChangeFP) (AccessBridge_PropertyChangeFP fp); + + typedef void (*SetJavaShutdownFP) (AccessBridge_JavaShutdownFP fp); + typedef void (*SetFocusGainedFP) (AccessBridge_FocusGainedFP fp); + typedef void (*SetFocusLostFP) (AccessBridge_FocusLostFP fp); + + typedef void (*SetCaretUpdateFP) (AccessBridge_CaretUpdateFP fp); + + typedef void (*SetMouseClickedFP) (AccessBridge_MouseClickedFP fp); + typedef void (*SetMouseEnteredFP) (AccessBridge_MouseEnteredFP fp); + typedef void (*SetMouseExitedFP) (AccessBridge_MouseExitedFP fp); + typedef void (*SetMousePressedFP) (AccessBridge_MousePressedFP fp); + typedef void (*SetMouseReleasedFP) (AccessBridge_MouseReleasedFP fp); + + typedef void (*SetMenuCanceledFP) (AccessBridge_MenuCanceledFP fp); + typedef void (*SetMenuDeselectedFP) (AccessBridge_MenuDeselectedFP fp); + typedef void (*SetMenuSelectedFP) (AccessBridge_MenuSelectedFP fp); + typedef void (*SetPopupMenuCanceledFP) (AccessBridge_PopupMenuCanceledFP fp); + typedef void (*SetPopupMenuWillBecomeInvisibleFP) (AccessBridge_PopupMenuWillBecomeInvisibleFP fp); + typedef void (*SetPopupMenuWillBecomeVisibleFP) (AccessBridge_PopupMenuWillBecomeVisibleFP fp); + + typedef void (*SetPropertyNameChangeFP) (AccessBridge_PropertyNameChangeFP fp); + typedef void (*SetPropertyDescriptionChangeFP) (AccessBridge_PropertyDescriptionChangeFP fp); + typedef void (*SetPropertyStateChangeFP) (AccessBridge_PropertyStateChangeFP fp); + typedef void (*SetPropertyValueChangeFP) (AccessBridge_PropertyValueChangeFP fp); + typedef void (*SetPropertySelectionChangeFP) (AccessBridge_PropertySelectionChangeFP fp); + typedef void (*SetPropertyTextChangeFP) (AccessBridge_PropertyTextChangeFP fp); + typedef void (*SetPropertyCaretChangeFP) (AccessBridge_PropertyCaretChangeFP fp); + typedef void (*SetPropertyVisibleDataChangeFP) (AccessBridge_PropertyVisibleDataChangeFP fp); + typedef void (*SetPropertyChildChangeFP) (AccessBridge_PropertyChildChangeFP fp); + typedef void (*SetPropertyActiveDescendentChangeFP) (AccessBridge_PropertyActiveDescendentChangeFP fp); + + typedef void (*SetPropertyTableModelChangeFP) (AccessBridge_PropertyTableModelChangeFP fp); + + typedef void (*ReleaseJavaObjectFP) (long vmID, Java_Object object); + + typedef BOOL (*GetVersionInfoFP) (long vmID, AccessBridgeVersionInfo *info); + + typedef BOOL (*IsJavaWindowFP) (HWND window); + typedef BOOL (*IsSameObjectFP) (long vmID, JOBJECT64 obj1, JOBJECT64 obj2); + typedef BOOL (*GetAccessibleContextFromHWNDFP) (HWND window, long *vmID, AccessibleContext *ac); + typedef HWND (*getHWNDFromAccessibleContextFP) (long vmID, AccessibleContext ac); + + typedef BOOL (*GetAccessibleContextAtFP) (long vmID, AccessibleContext acParent, + jint x, jint y, AccessibleContext *ac); + typedef BOOL (*GetAccessibleContextWithFocusFP) (HWND window, long *vmID, AccessibleContext *ac); + typedef BOOL (*GetAccessibleContextInfoFP) (long vmID, AccessibleContext ac, AccessibleContextInfo *info); + typedef AccessibleContext (*GetAccessibleChildFromContextFP) (long vmID, AccessibleContext ac, jint i); + typedef AccessibleContext (*GetAccessibleParentFromContextFP) (long vmID, AccessibleContext ac); + + /* begin AccessibleTable */ + typedef BOOL (*getAccessibleTableInfoFP) (long vmID, AccessibleContext ac, AccessibleTableInfo *tableInfo); + typedef BOOL (*getAccessibleTableCellInfoFP) (long vmID, AccessibleTable accessibleTable, + jint row, jint column, AccessibleTableCellInfo *tableCellInfo); + + typedef BOOL (*getAccessibleTableRowHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo); + typedef BOOL (*getAccessibleTableColumnHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo); + + typedef AccessibleContext (*getAccessibleTableRowDescriptionFP) (long vmID, AccessibleContext acParent, jint row); + typedef AccessibleContext (*getAccessibleTableColumnDescriptionFP) (long vmID, AccessibleContext acParent, jint column); + + typedef jint (*getAccessibleTableRowSelectionCountFP) (long vmID, AccessibleTable table); + typedef BOOL (*isAccessibleTableRowSelectedFP) (long vmID, AccessibleTable table, jint row); + typedef BOOL (*getAccessibleTableRowSelectionsFP) (long vmID, AccessibleTable table, jint count, + jint *selections); + + typedef jint (*getAccessibleTableColumnSelectionCountFP) (long vmID, AccessibleTable table); + typedef BOOL (*isAccessibleTableColumnSelectedFP) (long vmID, AccessibleTable table, jint column); + typedef BOOL (*getAccessibleTableColumnSelectionsFP) (long vmID, AccessibleTable table, jint count, + jint *selections); + + typedef jint (*getAccessibleTableRowFP) (long vmID, AccessibleTable table, jint index); + typedef jint (*getAccessibleTableColumnFP) (long vmID, AccessibleTable table, jint index); + typedef jint (*getAccessibleTableIndexFP) (long vmID, AccessibleTable table, jint row, jint column); + /* end AccessibleTable */ + + /* AccessibleRelationSet */ + typedef BOOL (*getAccessibleRelationSetFP) (long vmID, AccessibleContext accessibleContext, + AccessibleRelationSetInfo *relationSetInfo); + + /* AccessibleHypertext */ + typedef BOOL (*getAccessibleHypertextFP)(long vmID, AccessibleContext accessibleContext, + AccessibleHypertextInfo *hypertextInfo); + + typedef BOOL (*activateAccessibleHyperlinkFP)(long vmID, AccessibleContext accessibleContext, + AccessibleHyperlink accessibleHyperlink); + + typedef jint (*getAccessibleHyperlinkCountFP)(const long vmID, + const AccessibleContext accessibleContext); + + typedef BOOL (*getAccessibleHypertextExtFP) (const long vmID, + const AccessibleContext accessibleContext, + const jint nStartIndex, + AccessibleHypertextInfo *hypertextInfo); + + typedef jint (*getAccessibleHypertextLinkIndexFP)(const long vmID, + const AccessibleHypertext hypertext, + const jint nIndex); + + typedef BOOL (*getAccessibleHyperlinkFP)(const long vmID, + const AccessibleHypertext hypertext, + const jint nIndex, + AccessibleHyperlinkInfo *hyperlinkInfo); + + + /* Accessible KeyBindings, Icons and Actions */ + typedef BOOL (*getAccessibleKeyBindingsFP)(long vmID, AccessibleContext accessibleContext, + AccessibleKeyBindings *keyBindings); + + typedef BOOL (*getAccessibleIconsFP)(long vmID, AccessibleContext accessibleContext, + AccessibleIcons *icons); + + typedef BOOL (*getAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext, + AccessibleActions *actions); + + typedef BOOL (*doAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext, + AccessibleActionsToDo *actionsToDo, jint *failure); + + + /* AccessibleText */ + + typedef BOOL (*GetAccessibleTextInfoFP) (long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y); + typedef BOOL (*GetAccessibleTextItemsFP) (long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index); + typedef BOOL (*GetAccessibleTextSelectionInfoFP) (long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection); + typedef BOOL (*GetAccessibleTextAttributesFP) (long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes); + typedef BOOL (*GetAccessibleTextRectFP) (long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index); + typedef BOOL (*GetAccessibleTextLineBoundsFP) (long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex); + typedef BOOL (*GetAccessibleTextRangeFP) (long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len); + + typedef BOOL (*GetCurrentAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len); + typedef BOOL (*GetMaximumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len); + typedef BOOL (*GetMinimumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len); + + typedef void (*AddAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i); + typedef void (*ClearAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as); + typedef JOBJECT64 (*GetAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i); + typedef int (*GetAccessibleSelectionCountFromContextFP) (long vmID, AccessibleSelection as); + typedef BOOL (*IsAccessibleChildSelectedFromContextFP) (long vmID, AccessibleSelection as, int i); + typedef void (*RemoveAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i); + typedef void (*SelectAllAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as); + + /* Utility methods */ + + typedef BOOL (*setTextContentsFP) (const long vmID, const AccessibleContext ac, const wchar_t *text); + typedef AccessibleContext (*getParentWithRoleFP) (const long vmID, const AccessibleContext ac, const wchar_t *role); + typedef AccessibleContext (*getParentWithRoleElseRootFP) (const long vmID, const AccessibleContext ac, const wchar_t *role); + typedef AccessibleContext (*getTopLevelObjectFP) (const long vmID, const AccessibleContext ac); + typedef int (*getObjectDepthFP) (const long vmID, const AccessibleContext ac); + typedef AccessibleContext (*getActiveDescendentFP) (const long vmID, const AccessibleContext ac); + + + typedef BOOL (*getVirtualAccessibleNameFP) (const long vmID, const AccessibleContext accessibleContext, + wchar_t *name, int len); + + typedef BOOL (*requestFocusFP) (const long vmID, const AccessibleContext accessibleContext); + + typedef BOOL (*selectTextRangeFP) (const long vmID, const AccessibleContext accessibleContext, + const int startIndex, const int endIndex); + + typedef BOOL (*getTextAttributesInRangeFP) (const long vmID, const AccessibleContext accessibleContext, + const int startIndex, const int endIndex, + AccessibleTextAttributesInfo *attributes, short *len); + + typedef int (*getVisibleChildrenCountFP) (const long vmID, const AccessibleContext accessibleContext); + + typedef BOOL (*getVisibleChildrenFP) (const long vmID, const AccessibleContext accessibleContext, + const int startIndex, VisibleChildrenInfo *children); + + typedef BOOL (*setCaretPositionFP) (const long vmID, const AccessibleContext accessibleContext, const int position); + + typedef BOOL (*getCaretLocationFP) (long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index); + + typedef int (*getEventsWaitingFP) (); + + typedef struct AccessBridgeFPsTag { + Windows_runFP Windows_run; + + SetPropertyChangeFP SetPropertyChange; + + SetJavaShutdownFP SetJavaShutdown; + SetFocusGainedFP SetFocusGained; + SetFocusLostFP SetFocusLost; + + SetCaretUpdateFP SetCaretUpdate; + + SetMouseClickedFP SetMouseClicked; + SetMouseEnteredFP SetMouseEntered; + SetMouseExitedFP SetMouseExited; + SetMousePressedFP SetMousePressed; + SetMouseReleasedFP SetMouseReleased; + + SetMenuCanceledFP SetMenuCanceled; + SetMenuDeselectedFP SetMenuDeselected; + SetMenuSelectedFP SetMenuSelected; + SetPopupMenuCanceledFP SetPopupMenuCanceled; + SetPopupMenuWillBecomeInvisibleFP SetPopupMenuWillBecomeInvisible; + SetPopupMenuWillBecomeVisibleFP SetPopupMenuWillBecomeVisible; + + SetPropertyNameChangeFP SetPropertyNameChange; + SetPropertyDescriptionChangeFP SetPropertyDescriptionChange; + SetPropertyStateChangeFP SetPropertyStateChange; + SetPropertyValueChangeFP SetPropertyValueChange; + SetPropertySelectionChangeFP SetPropertySelectionChange; + SetPropertyTextChangeFP SetPropertyTextChange; + SetPropertyCaretChangeFP SetPropertyCaretChange; + SetPropertyVisibleDataChangeFP SetPropertyVisibleDataChange; + SetPropertyChildChangeFP SetPropertyChildChange; + SetPropertyActiveDescendentChangeFP SetPropertyActiveDescendentChange; + + SetPropertyTableModelChangeFP SetPropertyTableModelChange; + + ReleaseJavaObjectFP ReleaseJavaObject; + GetVersionInfoFP GetVersionInfo; + + IsJavaWindowFP IsJavaWindow; + IsSameObjectFP IsSameObject; + GetAccessibleContextFromHWNDFP GetAccessibleContextFromHWND; + getHWNDFromAccessibleContextFP getHWNDFromAccessibleContext; + + GetAccessibleContextAtFP GetAccessibleContextAt; + GetAccessibleContextWithFocusFP GetAccessibleContextWithFocus; + GetAccessibleContextInfoFP GetAccessibleContextInfo; + GetAccessibleChildFromContextFP GetAccessibleChildFromContext; + GetAccessibleParentFromContextFP GetAccessibleParentFromContext; + + getAccessibleTableInfoFP getAccessibleTableInfo; + getAccessibleTableCellInfoFP getAccessibleTableCellInfo; + + getAccessibleTableRowHeaderFP getAccessibleTableRowHeader; + getAccessibleTableColumnHeaderFP getAccessibleTableColumnHeader; + + getAccessibleTableRowDescriptionFP getAccessibleTableRowDescription; + getAccessibleTableColumnDescriptionFP getAccessibleTableColumnDescription; + + getAccessibleTableRowSelectionCountFP getAccessibleTableRowSelectionCount; + isAccessibleTableRowSelectedFP isAccessibleTableRowSelected; + getAccessibleTableRowSelectionsFP getAccessibleTableRowSelections; + + getAccessibleTableColumnSelectionCountFP getAccessibleTableColumnSelectionCount; + isAccessibleTableColumnSelectedFP isAccessibleTableColumnSelected; + getAccessibleTableColumnSelectionsFP getAccessibleTableColumnSelections; + + getAccessibleTableRowFP getAccessibleTableRow; + getAccessibleTableColumnFP getAccessibleTableColumn; + getAccessibleTableIndexFP getAccessibleTableIndex; + + getAccessibleRelationSetFP getAccessibleRelationSet; + + getAccessibleHypertextFP getAccessibleHypertext; + activateAccessibleHyperlinkFP activateAccessibleHyperlink; + getAccessibleHyperlinkCountFP getAccessibleHyperlinkCount; + getAccessibleHypertextExtFP getAccessibleHypertextExt; + getAccessibleHypertextLinkIndexFP getAccessibleHypertextLinkIndex; + getAccessibleHyperlinkFP getAccessibleHyperlink; + + getAccessibleKeyBindingsFP getAccessibleKeyBindings; + getAccessibleIconsFP getAccessibleIcons; + getAccessibleActionsFP getAccessibleActions; + doAccessibleActionsFP doAccessibleActions; + + GetAccessibleTextInfoFP GetAccessibleTextInfo; + GetAccessibleTextItemsFP GetAccessibleTextItems; + GetAccessibleTextSelectionInfoFP GetAccessibleTextSelectionInfo; + GetAccessibleTextAttributesFP GetAccessibleTextAttributes; + GetAccessibleTextRectFP GetAccessibleTextRect; + GetAccessibleTextLineBoundsFP GetAccessibleTextLineBounds; + GetAccessibleTextRangeFP GetAccessibleTextRange; + + GetCurrentAccessibleValueFromContextFP GetCurrentAccessibleValueFromContext; + GetMaximumAccessibleValueFromContextFP GetMaximumAccessibleValueFromContext; + GetMinimumAccessibleValueFromContextFP GetMinimumAccessibleValueFromContext; + + AddAccessibleSelectionFromContextFP AddAccessibleSelectionFromContext; + ClearAccessibleSelectionFromContextFP ClearAccessibleSelectionFromContext; + GetAccessibleSelectionFromContextFP GetAccessibleSelectionFromContext; + GetAccessibleSelectionCountFromContextFP GetAccessibleSelectionCountFromContext; + IsAccessibleChildSelectedFromContextFP IsAccessibleChildSelectedFromContext; + RemoveAccessibleSelectionFromContextFP RemoveAccessibleSelectionFromContext; + SelectAllAccessibleSelectionFromContextFP SelectAllAccessibleSelectionFromContext; + + setTextContentsFP setTextContents; + getParentWithRoleFP getParentWithRole; + getTopLevelObjectFP getTopLevelObject; + getParentWithRoleElseRootFP getParentWithRoleElseRoot; + getObjectDepthFP getObjectDepth; + getActiveDescendentFP getActiveDescendent; + + getVirtualAccessibleNameFP getVirtualAccessibleName; + requestFocusFP requestFocus; + selectTextRangeFP selectTextRange; + getTextAttributesInRangeFP getTextAttributesInRange; + getVisibleChildrenCountFP getVisibleChildrenCount; + getVisibleChildrenFP getVisibleChildren; + setCaretPositionFP setCaretPosition; + getCaretLocationFP getCaretLocation; + + getEventsWaitingFP getEventsWaiting; + + } AccessBridgeFPs; + + + /** + * Initialize the world + */ + BOOL initializeAccessBridge(); + BOOL shutdownAccessBridge(); + + /** + * Window routines + */ + BOOL IsJavaWindow(HWND window); + + // Returns the virtual machine ID and AccessibleContext for a top-level window + BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac); + + // Returns the HWND from the AccessibleContext of a top-level window + HWND getHWNDFromAccessibleContext(long vmID, AccessibleContext ac); + + + /** + * Event handling routines + */ + void SetJavaShutdown(AccessBridge_JavaShutdownFP fp); + void SetFocusGained(AccessBridge_FocusGainedFP fp); + void SetFocusLost(AccessBridge_FocusLostFP fp); + + void SetCaretUpdate(AccessBridge_CaretUpdateFP fp); + + void SetMouseClicked(AccessBridge_MouseClickedFP fp); + void SetMouseEntered(AccessBridge_MouseEnteredFP fp); + void SetMouseExited(AccessBridge_MouseExitedFP fp); + void SetMousePressed(AccessBridge_MousePressedFP fp); + void SetMouseReleased(AccessBridge_MouseReleasedFP fp); + + void SetMenuCanceled(AccessBridge_MenuCanceledFP fp); + void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp); + void SetMenuSelected(AccessBridge_MenuSelectedFP fp); + void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp); + void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp); + void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp); + + void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp); + void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp); + void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp); + void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp); + void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp); + void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp); + void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp); + void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp); + void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp); + void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp); + + void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp); + + + /** + * General routines + */ + void ReleaseJavaObject(long vmID, Java_Object object); + BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info); + HWND GetHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext); + + /** + * Accessible Context routines + */ + BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent, + jint x, jint y, AccessibleContext *ac); + BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac); + BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info); + AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index); + AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac); + + /** + * Accessible Text routines + */ + BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y); + BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index); + BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection); + BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes); + BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index); + BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex); + BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len); + + /* begin AccessibleTable routines */ + BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo); + + BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable, jint row, jint column, + AccessibleTableCellInfo *tableCellInfo); + + BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo); + BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo); + + AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row); + AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column); + + jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table); + BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row); + BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections); + + jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table); + BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column); + BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections); + + jint getAccessibleTableRow(long vmID, AccessibleTable table, jint index); + jint getAccessibleTableColumn(long vmID, AccessibleTable table, jint index); + jint getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column); + /* end AccessibleTable */ + + /* ----- AccessibleRelationSet routines */ + BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext, + AccessibleRelationSetInfo *relationSetInfo); + + /* ----- AccessibleHypertext routines */ + + /* + * Returns hypertext information associated with a component. + */ + BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext, + AccessibleHypertextInfo *hypertextInfo); + + /* + * Requests that a hyperlink be activated. + */ + BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext, + AccessibleHyperlink accessibleHyperlink); + + /* + * Returns the number of hyperlinks in a component + * Maps to AccessibleHypertext.getLinkCount. + * Returns -1 on error. + */ + jint getAccessibleHyperlinkCount(const long vmID, + const AccessibleHypertext hypertext); + + /* + * This method is used to iterate through the hyperlinks in a component. It + * returns hypertext information for a component starting at hyperlink index + * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will + * be returned for each call to this method. + * Returns FALSE on error. + */ + BOOL getAccessibleHypertextExt(const long vmID, + const AccessibleContext accessibleContext, + const jint nStartIndex, + /* OUT */ AccessibleHypertextInfo *hypertextInfo); + + /* + * Returns the index into an array of hyperlinks that is associated with + * a character index in document; maps to AccessibleHypertext.getLinkIndex + * Returns -1 on error. + */ + jint getAccessibleHypertextLinkIndex(const long vmID, + const AccessibleHypertext hypertext, + const jint nIndex); + + /* + * Returns the nth hyperlink in a document + * Maps to AccessibleHypertext.getLink. + * Returns FALSE on error + */ + BOOL getAccessibleHyperlink(const long vmID, + const AccessibleHypertext hypertext, + const jint nIndex, + /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo); + + /* Accessible KeyBindings, Icons and Actions */ + + /* + * Returns a list of key bindings associated with a component. + */ + BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext, + AccessibleKeyBindings *keyBindings); + + /* + * Returns a list of icons associate with a component. + */ + BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext, + AccessibleIcons *icons); + + /* + * Returns a list of actions that a component can perform. + */ + BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext, + AccessibleActions *actions); + + /* + * Request that a list of AccessibleActions be performed by a component. + * Returns TRUE if all actions are performed. Returns FALSE + * when the first requested action fails in which case "failure" + * contains the index of the action that failed. + */ + BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext, + AccessibleActionsToDo *actionsToDo, jint *failure); + + + + /* Additional utility methods */ + + /* + * Returns whether two object references refer to the same object. + */ + BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2); + + /** + * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and + * be editable. The maximum text length that can be set is MAX_STRING_SIZE - 1. + * Returns whether successful + */ + BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text); + + /** + * Returns the Accessible Context with the specified role that is the + * ancestor of a given object. The role is one of the role strings + * defined in AccessBridgePackages.h + * If there is no ancestor object that has the specified role, + * returns (AccessibleContext)0. + */ + AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext, + const wchar_t *role); + + /** + * Returns the Accessible Context with the specified role that is the + * ancestor of a given object. The role is one of the role strings + * defined in AccessBridgePackages.h. If an object with the specified + * role does not exist, returns the top level object for the Java Window. + * Returns (AccessibleContext)0 on error. + */ + AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext, + const wchar_t *role); + + /** + * Returns the Accessible Context for the top level object in + * a Java Window. This is same Accessible Context that is obtained + * from GetAccessibleContextFromHWND for that window. Returns + * (AccessibleContext)0 on error. + */ + AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext); + + /** + * Returns how deep in the object hierarchy a given object is. + * The top most object in the object hierarchy has an object depth of 0. + * Returns -1 on error. + */ + int getObjectDepth (const long vmID, const AccessibleContext accessibleContext); + + /** + * Returns the Accessible Context of the current ActiveDescendent of an object. + * This method assumes the ActiveDescendent is the component that is currently + * selected in a container object. + * Returns (AccessibleContext)0 on error or if there is no selection. + */ + AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext); + + /** + /** + * Accessible Value routines + */ + BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len); + BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len); + BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len); + + /** + * Accessible Selection routines + */ + void AddAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i); + void ClearAccessibleSelectionFromContext(long vmID, AccessibleSelection as); + JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i); + int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as); + BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i); + void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i); + void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as); + + /** + * Additional methods for Teton + */ + + /** + * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns + * whether successful. + * + * Bug ID 4916682 - Implement JAWS AccessibleName policy + */ + BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext, + wchar_t *name, int len); + + /** + * Request focus for a component. Returns whether successful. + * + * Bug ID 4944757 - requestFocus method needed + */ + BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext); + + /** + * Selects text between two indices. Selection includes the text at the start index + * and the text at the end index. Returns whether successful. + * + * Bug ID 4944758 - selectTextRange method needed + */ + BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext, const int startIndex, + const int endIndex); + + /** + * Get text attributes between two indices. The attribute list includes the text at the + * start index and the text at the end index. Returns whether successful; + * + * Bug ID 4944761 - getTextAttributes between two indices method needed + */ + BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext, + const int startIndex, const int endIndex, + AccessibleTextAttributesInfo *attributes, short *len); + + /** + * Returns the number of visible children of a component. Returns -1 on error. + * + * Bug ID 4944762- getVisibleChildren for list-like components needed + */ + int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext); + + /** + * Gets the visible children of an AccessibleContext. Returns whether successful. + * + * Bug ID 4944762- getVisibleChildren for list-like components needed + */ + BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext, + const int startIndex, + VisibleChildrenInfo *visibleChildrenInfo); + + /** + * Set the caret to a text position. Returns whether successful. + * + * Bug ID 4944770 - setCaretPosition method needed + */ + BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext, + const int position); + + /** + * Gets the text caret location + */ + BOOL getCaretLocation(long vmID, AccessibleContext ac, + AccessibleTextRectInfo *rectInfo, jint index); + + /** + * Gets the number of events waiting to fire + */ + int getEventsWaiting(); + +#ifdef __cplusplus +} +#endif diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgePackages.h b/arthas-beans/src/main/native/head/windows/AccessBridgePackages.h new file mode 100755 index 000000000..478f7c636 --- /dev/null +++ b/arthas-beans/src/main/native/head/windows/AccessBridgePackages.h @@ -0,0 +1,2215 @@ +/* + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * Header file for packages of paramaters passed between Java Accessibility + * and native Assistive Technologies + */ + +#ifndef __AccessBridgePackages_H__ +#define __AccessBridgePackages_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ACCESSBRIDGE_ARCH_LEGACY +typedef jobject JOBJECT64; +typedef HWND ABHWND64; +#define ABHandleToLong +#define ABLongToHandle +#else +typedef jlong JOBJECT64; +typedef long ABHWND64; +#define ABHandleToLong HandleToLong +#define ABLongToHandle LongToHandle +#endif + +#define MAX_BUFFER_SIZE 10240 +#define MAX_STRING_SIZE 1024 +#define SHORT_STRING_SIZE 256 + + // object types + typedef JOBJECT64 AccessibleContext; + typedef JOBJECT64 AccessibleText; + typedef JOBJECT64 AccessibleValue; + typedef JOBJECT64 AccessibleSelection; + typedef JOBJECT64 Java_Object; + typedef JOBJECT64 PropertyChangeEvent; + typedef JOBJECT64 FocusEvent; + typedef JOBJECT64 CaretEvent; + typedef JOBJECT64 MouseEvent; + typedef JOBJECT64 MenuEvent; + typedef JOBJECT64 AccessibleTable; + typedef JOBJECT64 AccessibleHyperlink; + typedef JOBJECT64 AccessibleHypertext; + + /** + ****************************************************** + * Java event types + ****************************************************** + */ + +#define cPropertyChangeEvent (jlong) 1 // 1 +#define cFocusGainedEvent (jlong) 2 // 2 +#define cFocusLostEvent (jlong) 4 // 4 +#define cCaretUpdateEvent (jlong) 8 // 8 +#define cMouseClickedEvent (jlong) 16 // 10 +#define cMouseEnteredEvent (jlong) 32 // 20 +#define cMouseExitedEvent (jlong) 64 // 40 +#define cMousePressedEvent (jlong) 128 // 80 +#define cMouseReleasedEvent (jlong) 256 // 100 +#define cMenuCanceledEvent (jlong) 512 // 200 +#define cMenuDeselectedEvent (jlong) 1024 // 400 +#define cMenuSelectedEvent (jlong) 2048 // 800 +#define cPopupMenuCanceledEvent (jlong) 4096 // 1000 +#define cPopupMenuWillBecomeInvisibleEvent (jlong) 8192 // 2000 +#define cPopupMenuWillBecomeVisibleEvent (jlong) 16384 // 4000 +#define cJavaShutdownEvent (jlong) 32768 // 8000 + + /** + ****************************************************** + * Accessible Roles + * Defines all AccessibleRoles in Local.US + ****************************************************** + */ + + /** + * Object is used to alert the user about something. + */ +#define ACCESSIBLE_ALERT L"alert" + + /** + * The header for a column of data. + */ +#define ACCESSIBLE_COLUMN_HEADER L"column header" + + /** + * Object that can be drawn into and is used to trap + * events. + * see ACCESSIBLE_FRAME + * see ACCESSIBLE_GLASS_PANE + * see ACCESSIBLE_LAYERED_PANE + */ +#define ACCESSIBLE_CANVAS L"canvas" + + /** + * A list of choices the user can select from. Also optionally + * allows the user to enter a choice of their own. + */ +#define ACCESSIBLE_COMBO_BOX L"combo box" + + /** + * An iconified internal frame in a DESKTOP_PANE. + * see ACCESSIBLE_DESKTOP_PANE + * see ACCESSIBLE_INTERNAL_FRAME + */ +#define ACCESSIBLE_DESKTOP_ICON L"desktop icon" + + /** + * A frame-like object that is clipped by a desktop pane. The + * desktop pane, internal frame, and desktop icon objects are + * often used to create multiple document interfaces within an + * application. + * see ACCESSIBLE_DESKTOP_ICON + * see ACCESSIBLE_DESKTOP_PANE + * see ACCESSIBLE_FRAME + */ +#define ACCESSIBLE_INTERNAL_FRAME L"internal frame" + + /** + * A pane that supports internal frames and + * iconified versions of those internal frames. + * see ACCESSIBLE_DESKTOP_ICON + * see ACCESSIBLE_INTERNAL_FRAME + */ +#define ACCESSIBLE_DESKTOP_PANE L"desktop pane" + + /** + * A specialized pane whose primary use is inside a DIALOG + * see ACCESSIBLE_DIALOG + */ +#define ACCESSIBLE_OPTION_PANE L"option pane" + + /** + * A top level window with no title or border. + * see ACCESSIBLE_FRAME + * see ACCESSIBLE_DIALOG + */ +#define ACCESSIBLE_WINDOW L"window" + + /** + * A top level window with a title bar, border, menu bar, etc. It is + * often used as the primary window for an application. + * see ACCESSIBLE_DIALOG + * see ACCESSIBLE_CANVAS + * see ACCESSIBLE_WINDOW + */ +#define ACCESSIBLE_FRAME L"frame" + + /** + * A top level window with title bar and a border. A dialog is similar + * to a frame, but it has fewer properties and is often used as a + * secondary window for an application. + * see ACCESSIBLE_FRAME + * see ACCESSIBLE_WINDOW + */ +#define ACCESSIBLE_DIALOG L"dialog" + + /** + * A specialized dialog that lets the user choose a color. + */ +#define ACCESSIBLE_COLOR_CHOOSER L"color chooser" + + + /** + * A pane that allows the user to navigate through + * and select the contents of a directory. May be used + * by a file chooser. + * see ACCESSIBLE_FILE_CHOOSER + */ +#define ACCESSIBLE_DIRECTORY_PANE L"directory pane" + + /** + * A specialized dialog that displays the files in the directory + * and lets the user select a file, browse a different directory, + * or specify a filename. May use the directory pane to show the + * contents of a directory. + * see ACCESSIBLE_DIRECTORY_PANE + */ +#define ACCESSIBLE_FILE_CHOOSER L"file chooser" + + /** + * An object that fills up space in a user interface. It is often + * used in interfaces to tweak the spacing between components, + * but serves no other purpose. + */ +#define ACCESSIBLE_FILLER L"filler" + + /** + * A hypertext anchor + */ +#define ACCESSIBLE_HYPERLINK L"hyperlink" + + /** + * A small fixed size picture, typically used to decorate components. + */ +#define ACCESSIBLE_ICON L"icon" + + /** + * An object used to present an icon or short string in an interface. + */ +#define ACCESSIBLE_LABEL L"label" + + /** + * A specialized pane that has a glass pane and a layered pane as its + * children. + * see ACCESSIBLE_GLASS_PANE + * see ACCESSIBLE_LAYERED_PANE + */ +#define ACCESSIBLE_ROOT_PANE L"root pane" + + /** + * A pane that is guaranteed to be painted on top + * of all panes beneath it. + * see ACCESSIBLE_ROOT_PANE + * see ACCESSIBLE_CANVAS + */ +#define ACCESSIBLE_GLASS_PANE L"glass pane" + + /** + * A specialized pane that allows its children to be drawn in layers, + * providing a form of stacking order. This is usually the pane that + * holds the menu bar as well as the pane that contains most of the + * visual components in a window. + * see ACCESSIBLE_GLASS_PANE + * see ACCESSIBLE_ROOT_PANE + */ +#define ACCESSIBLE_LAYERED_PANE L"layered pane" + + /** + * An object that presents a list of objects to the user and allows the + * user to select one or more of them. A list is usually contained + * within a scroll pane. + * see ACCESSIBLE_SCROLL_PANE + * see ACCESSIBLE_LIST_ITEM + */ +#define ACCESSIBLE_LIST L"list" + + /** + * An object that presents an element in a list. A list is usually + * contained within a scroll pane. + * see ACCESSIBLE_SCROLL_PANE + * see ACCESSIBLE_LIST + */ +#define ACCESSIBLE_LIST_ITEM L"list item" + + /** + * An object usually drawn at the top of the primary dialog box of + * an application that contains a list of menus the user can choose + * from. For example, a menu bar might contain menus for "File," + * "Edit," and "Help." + * see ACCESSIBLE_MENU + * see ACCESSIBLE_POPUP_MENU + * see ACCESSIBLE_LAYERED_PANE + */ +#define ACCESSIBLE_MENU_BAR L"menu bar" + + /** + * A temporary window that is usually used to offer the user a + * list of choices, and then hides when the user selects one of + * those choices. + * see ACCESSIBLE_MENU + * see ACCESSIBLE_MENU_ITEM + */ +#define ACCESSIBLE_POPUP_MENU L"popup menu" + + /** + * An object usually found inside a menu bar that contains a list + * of actions the user can choose from. A menu can have any object + * as its children, but most often they are menu items, other menus, + * or rudimentary objects such as radio buttons, check boxes, or + * separators. For example, an application may have an "Edit" menu + * that contains menu items for "Cut" and "Paste." + * see ACCESSIBLE_MENU_BAR + * see ACCESSIBLE_MENU_ITEM + * see ACCESSIBLE_SEPARATOR + * see ACCESSIBLE_RADIO_BUTTON + * see ACCESSIBLE_CHECK_BOX + * see ACCESSIBLE_POPUP_MENU + */ +#define ACCESSIBLE_MENU L"menu" + + /** + * An object usually contained in a menu that presents an action + * the user can choose. For example, the "Cut" menu item in an + * "Edit" menu would be an action the user can select to cut the + * selected area of text in a document. + * see ACCESSIBLE_MENU_BAR + * see ACCESSIBLE_SEPARATOR + * see ACCESSIBLE_POPUP_MENU + */ +#define ACCESSIBLE_MENU_ITEM L"menu item" + + /** + * An object usually contained in a menu to provide a visual + * and logical separation of the contents in a menu. For example, + * the "File" menu of an application might contain menu items for + * "Open," "Close," and "Exit," and will place a separator between + * "Close" and "Exit" menu items. + * see ACCESSIBLE_MENU + * see ACCESSIBLE_MENU_ITEM + */ +#define ACCESSIBLE_SEPARATOR L"separator" + + /** + * An object that presents a series of panels (or page tabs), one at a + * time, through some mechanism provided by the object. The most common + * mechanism is a list of tabs at the top of the panel. The children of + * a page tab list are all page tabs. + * see ACCESSIBLE_PAGE_TAB + */ +#define ACCESSIBLE_PAGE_TAB_LIST L"page tab list" + + /** + * An object that is a child of a page tab list. Its sole child is + * the panel that is to be presented to the user when the user + * selects the page tab from the list of tabs in the page tab list. + * see ACCESSIBLE_PAGE_TAB_LIST + */ +#define ACCESSIBLE_PAGE_TAB L"page tab" + + /** + * A generic container that is often used to group objects. + */ +#define ACCESSIBLE_PANEL L"panel" + + /** + * An object used to indicate how much of a task has been completed. + */ +#define ACCESSIBLE_PROGRESS_BAR L"progress bar" + + /** + * A text object used for passwords, or other places where the + * text contents is not shown visibly to the user + */ +#define ACCESSIBLE_PASSWORD_TEXT L"password text" + + /** + * An object the user can manipulate to tell the application to do + * something. + * see ACCESSIBLE_CHECK_BOX + * see ACCESSIBLE_TOGGLE_BUTTON + * see ACCESSIBLE_RADIO_BUTTON + */ +#define ACCESSIBLE_PUSH_BUTTON L"push button" + + /** + * A specialized push button that can be checked or unchecked, but + * does not provide a separate indicator for the current state. + * see ACCESSIBLE_PUSH_BUTTON + * see ACCESSIBLE_CHECK_BOX + * see ACCESSIBLE_RADIO_BUTTON + */ +#define ACCESSIBLE_TOGGLE_BUTTON L"toggle button" + + /** + * A choice that can be checked or unchecked and provides a + * separate indicator for the current state. + * see ACCESSIBLE_PUSH_BUTTON + * see ACCESSIBLE_TOGGLE_BUTTON + * see ACCESSIBLE_RADIO_BUTTON + */ +#define ACCESSIBLE_CHECK_BOX L"check box" + + /** + * A specialized check box that will cause other radio buttons in the + * same group to become unchecked when this one is checked. + * see ACCESSIBLE_PUSH_BUTTON + * see ACCESSIBLE_TOGGLE_BUTTON + * see ACCESSIBLE_CHECK_BOX + */ +#define ACCESSIBLE_RADIO_BUTTON L"radio button" + + /** + * The header for a row of data. + */ +#define ACCESSIBLE_ROW_HEADER L"row header" + + /** + * An object that allows a user to incrementally view a large amount + * of information. Its children can include scroll bars and a viewport. + * see ACCESSIBLE_SCROLL_BAR + * see ACCESSIBLE_VIEWPORT + */ +#define ACCESSIBLE_SCROLL_PANE L"scroll pane" + + /** + * An object usually used to allow a user to incrementally view a + * large amount of data. Usually used only by a scroll pane. + * see ACCESSIBLE_SCROLL_PANE + */ +#define ACCESSIBLE_SCROLL_BAR L"scroll bar" + + /** + * An object usually used in a scroll pane. It represents the portion + * of the entire data that the user can see. As the user manipulates + * the scroll bars, the contents of the viewport can change. + * see ACCESSIBLE_SCROLL_PANE + */ +#define ACCESSIBLE_VIEWPORT L"viewport" + + /** + * An object that allows the user to select from a bounded range. For + * example, a slider might be used to select a number between 0 and 100. + */ +#define ACCESSIBLE_SLIDER L"slider" + + /** + * A specialized panel that presents two other panels at the same time. + * Between the two panels is a divider the user can manipulate to make + * one panel larger and the other panel smaller. + */ +#define ACCESSIBLE_SPLIT_PANE L"split pane" + + /** + * An object used to present information in terms of rows and columns. + * An example might include a spreadsheet application. + */ +#define ACCESSIBLE_TABLE L"table" + + /** + * An object that presents text to the user. The text is usually + * editable by the user as opposed to a label. + * see ACCESSIBLE_LABEL + */ +#define ACCESSIBLE_TEXT L"text" + + /** + * An object used to present hierarchical information to the user. + * The individual nodes in the tree can be collapsed and expanded + * to provide selective disclosure of the tree's contents. + */ +#define ACCESSIBLE_TREE L"tree" + + /** + * A bar or palette usually composed of push buttons or toggle buttons. + * It is often used to provide the most frequently used functions for an + * application. + */ +#define ACCESSIBLE_TOOL_BAR L"tool bar" + + /** + * An object that provides information about another object. The + * accessibleDescription property of the tool tip is often displayed + * to the user in a small L"help bubble" when the user causes the + * mouse to hover over the object associated with the tool tip. + */ +#define ACCESSIBLE_TOOL_TIP L"tool tip" + + /** + * An AWT component, but nothing else is known about it. + * see ACCESSIBLE_SWING_COMPONENT + * see ACCESSIBLE_UNKNOWN + */ +#define ACCESSIBLE_AWT_COMPONENT L"awt component" + + /** + * A Swing component, but nothing else is known about it. + * see ACCESSIBLE_AWT_COMPONENT + * see ACCESSIBLE_UNKNOWN + */ +#define ACCESSIBLE_SWING_COMPONENT L"swing component" + + /** + * The object contains some Accessible information, but its role is + * not known. + * see ACCESSIBLE_AWT_COMPONENT + * see ACCESSIBLE_SWING_COMPONENT + */ +#define ACCESSIBLE_UNKNOWN L"unknown" + + /** + * A STATUS_BAR is an simple component that can contain + * multiple labels of status information to the user. + */ +#define ACCESSIBLE_STATUS_BAR L"status bar" + + /** + * A DATE_EDITOR is a component that allows users to edit + * java.util.Date and java.util.Time objects + */ +#define ACCESSIBLE_DATE_EDITOR L"date editor" + + /** + * A SPIN_BOX is a simple spinner component and its main use + * is for simple numbers. + */ +#define ACCESSIBLE_SPIN_BOX L"spin box" + + /** + * A FONT_CHOOSER is a component that lets the user pick various + * attributes for fonts. + */ +#define ACCESSIBLE_FONT_CHOOSER L"font chooser" + + /** + * A GROUP_BOX is a simple container that contains a border + * around it and contains components inside it. + */ +#define ACCESSIBLE_GROUP_BOX L"group box" + + /** + * A text header + */ +#define ACCESSIBLE_HEADER L"header" + + /** + * A text footer + */ +#define ACCESSIBLE_FOOTER L"footer" + + /** + * A text paragraph + */ +#define ACCESSIBLE_PARAGRAPH L"paragraph" + + /** + * A ruler is an object used to measure distance + */ +#define ACCESSIBLE_RULER L"ruler" + + /** + * A role indicating the object acts as a formula for + * calculating a value. An example is a formula in + * a spreadsheet cell. + */ +#define ACCESSIBLE_EDITBAR L"editbar" + + /** + * A role indicating the object monitors the progress + * of some operation. + */ +#define PROGRESS_MONITOR L"progress monitor" + + + /** + ****************************************************** + * Accessibility event types + ****************************************************** + */ + +#define cPropertyNameChangeEvent (jlong) 1 // 1 +#define cPropertyDescriptionChangeEvent (jlong) 2 // 2 +#define cPropertyStateChangeEvent (jlong) 4 // 4 +#define cPropertyValueChangeEvent (jlong) 8 // 8 +#define cPropertySelectionChangeEvent (jlong) 16 // 10 +#define cPropertyTextChangeEvent (jlong) 32 // 20 +#define cPropertyCaretChangeEvent (jlong) 64 // 40 +#define cPropertyVisibleDataChangeEvent (jlong) 128 // 80 +#define cPropertyChildChangeEvent (jlong) 256 // 100 +#define cPropertyActiveDescendentChangeEvent (jlong) 512 // 200 +#define cPropertyTableModelChangeEvent (jlong) 1024 // 400 + + /** + ****************************************************** + * optional AccessibleContext interfaces + * + * This version of the bridge reuses the accessibleValue + * field in the AccessibleContextInfo struct to represent + * additional optional interfaces that are supported by + * the Java AccessibleContext. This is backwardly compatable + * because the old accessibleValue was set to the BOOL + * value TRUE (i.e., 1) if the AccessibleValue interface is + * supported. + ****************************************************** + */ + +#define cAccessibleValueInterface (jlong) 1 // 1 << 1 (TRUE) +#define cAccessibleActionInterface (jlong) 2 // 1 << 2 +#define cAccessibleComponentInterface (jlong) 4 // 1 << 3 +#define cAccessibleSelectionInterface (jlong) 8 // 1 << 4 +#define cAccessibleTableInterface (jlong) 16 // 1 << 5 +#define cAccessibleTextInterface (jlong) 32 // 1 << 6 +#define cAccessibleHypertextInterface (jlong) 64 // 1 << 7 + + + /** + ****************************************************** + * Accessibility information bundles + ****************************************************** + */ + + typedef struct AccessBridgeVersionInfoTag { + wchar_t VMversion[SHORT_STRING_SIZE]; // output of "java -version" + wchar_t bridgeJavaClassVersion[SHORT_STRING_SIZE]; // version of the AccessBridge.class + wchar_t bridgeJavaDLLVersion[SHORT_STRING_SIZE]; // version of JavaAccessBridge.dll + wchar_t bridgeWinDLLVersion[SHORT_STRING_SIZE]; // version of WindowsAccessBridge.dll + } AccessBridgeVersionInfo; + + + typedef struct AccessibleContextInfoTag { + wchar_t name[MAX_STRING_SIZE]; // the AccessibleName of the object + wchar_t description[MAX_STRING_SIZE]; // the AccessibleDescription of the object + + wchar_t role[SHORT_STRING_SIZE]; // localized AccesibleRole string + wchar_t role_en_US[SHORT_STRING_SIZE]; // AccesibleRole string in the en_US locale + wchar_t states[SHORT_STRING_SIZE]; // localized AccesibleStateSet string (comma separated) + wchar_t states_en_US[SHORT_STRING_SIZE]; // AccesibleStateSet string in the en_US locale (comma separated) + + jint indexInParent; // index of object in parent + jint childrenCount; // # of children, if any + + jint x; // screen coords in pixels + jint y; // " + jint width; // pixel width of object + jint height; // pixel height of object + + BOOL accessibleComponent; // flags for various additional + BOOL accessibleAction; // Java Accessibility interfaces + BOOL accessibleSelection; // FALSE if this object doesn't + BOOL accessibleText; // implement the additional interface + // in question + + // BOOL accessibleValue; // old BOOL indicating whether AccessibleValue is supported + BOOL accessibleInterfaces; // new bitfield containing additional interface flags + + } AccessibleContextInfo; + + + + // AccessibleText packages + typedef struct AccessibleTextInfoTag { + jint charCount; // # of characters in this text object + jint caretIndex; // index of caret + jint indexAtPoint; // index at the passsed in point + } AccessibleTextInfo; + + typedef struct AccessibleTextItemsInfoTag { + wchar_t letter; + wchar_t word[SHORT_STRING_SIZE]; + wchar_t sentence[MAX_STRING_SIZE]; + } AccessibleTextItemsInfo; + + typedef struct AccessibleTextSelectionInfoTag { + jint selectionStartIndex; + jint selectionEndIndex; + wchar_t selectedText[MAX_STRING_SIZE]; + } AccessibleTextSelectionInfo; + + typedef struct AccessibleTextRectInfoTag { + jint x; // bounding rect of char at index + jint y; // " + jint width; // " + jint height; // " + } AccessibleTextRectInfo; + + // standard attributes for text; note: tabstops are not supported + typedef struct AccessibleTextAttributesInfoTag { + BOOL bold; + BOOL italic; + BOOL underline; + BOOL strikethrough; + BOOL superscript; + BOOL subscript; + + wchar_t backgroundColor[SHORT_STRING_SIZE]; + wchar_t foregroundColor[SHORT_STRING_SIZE]; + wchar_t fontFamily[SHORT_STRING_SIZE]; + jint fontSize; + + jint alignment; + jint bidiLevel; + + jfloat firstLineIndent; + jfloat leftIndent; + jfloat rightIndent; + jfloat lineSpacing; + jfloat spaceAbove; + jfloat spaceBelow; + + wchar_t fullAttributesString[MAX_STRING_SIZE]; + } AccessibleTextAttributesInfo; + + /** + ****************************************************** + * IPC management typedefs + ****************************************************** + */ + +#define cMemoryMappedNameSize 255 + + /** + * sent by the WindowsDLL -> the memory-mapped file is setup + * + */ + typedef struct MemoryMappedFileCreatedPackageTag { +// HWND bridgeWindow; // redundant, but easier to get to here... + ABHWND64 bridgeWindow; // redundant, but easier to get to here... + char filename[cMemoryMappedNameSize]; + } MemoryMappedFileCreatedPackage; + + + + + /** + * sent when a new JavaVM attaches to the Bridge + * + */ + typedef struct JavaVMCreatedPackageTag { + ABHWND64 bridgeWindow; + long vmID; + } JavaVMCreatedPackage; + + /** + * sent when a JavaVM detatches from the Bridge + * + */ + typedef struct JavaVMDestroyedPackageTag { + ABHWND64 bridgeWindow; + } JavaVMDestroyedPackage; + + /** + * sent when a new AT attaches to the Bridge + * + */ + typedef struct WindowsATCreatedPackageTag { + ABHWND64 bridgeWindow; + } WindowsATCreatedPackage; + + /** + * sent when an AT detatches from the Bridge + * + */ + typedef struct WindowsATDestroyedPackageTag { + ABHWND64 bridgeWindow; + } WindowsATDestroyedPackage; + + + /** + * sent by JVM Bridges in response to a WindowsATCreate + * message; saying "howdy, welcome to the neighborhood" + * + */ + typedef struct JavaVMPresentNotificationPackageTag { + ABHWND64 bridgeWindow; + long vmID; + } JavaVMPresentNotificationPackage; + + /** + * sent by AT Bridges in response to a JavaVMCreate + * message; saying "howdy, welcome to the neighborhood" + * + */ + typedef struct WindowsATPresentNotificationPackageTag { + ABHWND64 bridgeWindow; + } WindowsATPresentNotificationPackage; + + + /** + ****************************************************** + * Core packages + ****************************************************** + */ + + typedef struct ReleaseJavaObjectPackageTag { + long vmID; + JOBJECT64 object; + } ReleaseJavaObjectPackage; + + typedef struct GetAccessBridgeVersionPackageTag { + long vmID; // can't get VM info w/out a VM! + AccessBridgeVersionInfo rVersionInfo; + } GetAccessBridgeVersionPackage; + + typedef struct IsSameObjectPackageTag { + long vmID; + JOBJECT64 obj1; + JOBJECT64 obj2; + jboolean rResult; + } IsSameObjectPackage; + + /** + ****************************************************** + * Windows packages + ****************************************************** + */ + + typedef struct IsJavaWindowPackageTag { + jint window; + jboolean rResult; + } IsJavaWindowPackage; + + typedef struct GetAccessibleContextFromHWNDPackageTag { + jint window; + long rVMID; + JOBJECT64 rAccessibleContext; + } GetAccessibleContextFromHWNDPackage; + + typedef struct GetHWNDFromAccessibleContextPackageTag { + JOBJECT64 accessibleContext; + ABHWND64 rHWND; + } GetHWNDFromAccessibleContextPackage; + + /** +****************************************************** +* AccessibleContext packages +****************************************************** +*/ + + typedef struct GetAccessibleContextAtPackageTag { + jint x; + jint y; + long vmID; + JOBJECT64 AccessibleContext; // look within this AC + JOBJECT64 rAccessibleContext; + } GetAccessibleContextAtPackage; + + typedef struct GetAccessibleContextWithFocusPackageTag { + long rVMID; + JOBJECT64 rAccessibleContext; + } GetAccessibleContextWithFocusPackage; + + typedef struct GetAccessibleContextInfoPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + AccessibleContextInfo rAccessibleContextInfo; + } GetAccessibleContextInfoPackage; + + typedef struct GetAccessibleChildFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint childIndex; + JOBJECT64 rAccessibleContext; + } GetAccessibleChildFromContextPackage; + + typedef struct GetAccessibleParentFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + JOBJECT64 rAccessibleContext; + } GetAccessibleParentFromContextPackage; + + /** +****************************************************** +* AccessibleTable packages +****************************************************** +*/ + +#define MAX_TABLE_SELECTIONS 64 + + // table information + typedef struct AccessibleTableInfoTag { + JOBJECT64 caption; // AccesibleContext + JOBJECT64 summary; // AccessibleContext + jint rowCount; + jint columnCount; + JOBJECT64 accessibleContext; + JOBJECT64 accessibleTable; + } AccessibleTableInfo; + + typedef struct GetAccessibleTableInfoPackageTag { + long vmID; + JOBJECT64 accessibleContext; + AccessibleTableInfo rTableInfo; + } GetAccessibleTableInfoPackage; + + // table cell information + typedef struct AccessibleTableCellInfoTag { + JOBJECT64 accessibleContext; + jint index; + jint row; + jint column; + jint rowExtent; + jint columnExtent; + jboolean isSelected; + } AccessibleTableCellInfo; + + typedef struct GetAccessibleTableCellInfoPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint row; + jint column; + AccessibleTableCellInfo rTableCellInfo; + } GetAccessibleTableCellInfoPackage; + + typedef struct GetAccessibleTableRowHeaderPackageTag { + long vmID; + JOBJECT64 accessibleContext; + AccessibleTableInfo rTableInfo; + } GetAccessibleTableRowHeaderPackage; + + typedef struct GetAccessibleTableColumnHeaderPackageTag { + long vmID; + JOBJECT64 accessibleContext; + AccessibleTableInfo rTableInfo; + } GetAccessibleTableColumnHeaderPackage; + + typedef struct GetAccessibleTableRowDescriptionPackageTag { + long vmID; + JOBJECT64 accessibleContext; + jint row; + JOBJECT64 rAccessibleContext; + } GetAccessibleTableRowDescriptionPackage; + + typedef struct GetAccessibleTableColumnDescriptionPackageTag { + long vmID; + JOBJECT64 accessibleContext; + jint column; + JOBJECT64 rAccessibleContext; + } GetAccessibleTableColumnDescriptionPackage; + + typedef struct GetAccessibleTableRowSelectionCountPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint rCount; + } GetAccessibleTableRowSelectionCountPackage; + + typedef struct IsAccessibleTableRowSelectedPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint row; + jboolean rResult; + } IsAccessibleTableRowSelectedPackage; + + typedef struct GetAccessibleTableRowSelectionsPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint count; + jint rSelections[MAX_TABLE_SELECTIONS]; + } GetAccessibleTableRowSelectionsPackage; + + typedef struct GetAccessibleTableColumnSelectionCountPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint rCount; + } GetAccessibleTableColumnSelectionCountPackage; + + typedef struct IsAccessibleTableColumnSelectedPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint column; + jboolean rResult; + } IsAccessibleTableColumnSelectedPackage; + + typedef struct GetAccessibleTableColumnSelectionsPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint count; + jint rSelections[MAX_TABLE_SELECTIONS]; + } GetAccessibleTableColumnSelectionsPackage; + + + typedef struct GetAccessibleTableRowPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint index; + jint rRow; + } GetAccessibleTableRowPackage; + + typedef struct GetAccessibleTableColumnPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint index; + jint rColumn; + } GetAccessibleTableColumnPackage; + + typedef struct GetAccessibleTableIndexPackageTag { + long vmID; + JOBJECT64 accessibleTable; + jint row; + jint column; + jint rIndex; + } GetAccessibleTableIndexPackage; + + + /** + ****************************************************** + * AccessibleRelationSet packages + ****************************************************** + */ + +#define MAX_RELATION_TARGETS 25 +#define MAX_RELATIONS 5 + + typedef struct AccessibleRelationInfoTag { + wchar_t key[SHORT_STRING_SIZE]; + jint targetCount; + JOBJECT64 targets[MAX_RELATION_TARGETS]; // AccessibleContexts + } AccessibleRelationInfo; + + typedef struct AccessibleRelationSetInfoTag { + jint relationCount; + AccessibleRelationInfo relations[MAX_RELATIONS]; + } AccessibleRelationSetInfo; + + typedef struct GetAccessibleRelationSetPackageTag { + long vmID; + JOBJECT64 accessibleContext; + AccessibleRelationSetInfo rAccessibleRelationSetInfo; + } GetAccessibleRelationSetPackage; + + /** + ****************************************************** + * AccessibleHypertext packagess + ****************************************************** + */ + +#define MAX_HYPERLINKS 64 // maximum number of hyperlinks returned + + // hyperlink information + typedef struct AccessibleHyperlinkInfoTag { + wchar_t text[SHORT_STRING_SIZE]; // the hyperlink text + jint startIndex; //index in the hypertext document where the link begins + jint endIndex; //index in the hypertext document where the link ends + JOBJECT64 accessibleHyperlink; // AccessibleHyperlink object + } AccessibleHyperlinkInfo; + + // hypertext information + typedef struct AccessibleHypertextInfoTag { + jint linkCount; // number of hyperlinks + AccessibleHyperlinkInfo links[MAX_HYPERLINKS]; // the hyperlinks + JOBJECT64 accessibleHypertext; // AccessibleHypertext object + } AccessibleHypertextInfo; + + // struct for sending a message to get the hypertext for an AccessibleContext + typedef struct GetAccessibleHypertextPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // AccessibleContext with hypertext + AccessibleHypertextInfo rAccessibleHypertextInfo; // returned hypertext + } GetAccessibleHypertextPackage; + + // struct for sending an message to activate a hyperlink + typedef struct ActivateAccessibleHyperlinkPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // AccessibleContext containing the link + JOBJECT64 accessibleHyperlink; // the link to activate + BOOL rResult; // hyperlink activation return value + } ActivateAccessibleHyperlinkPackage; + + // struct for sending a message to get the number of hyperlinks in a component + typedef struct GetAccessibleHyperlinkCountPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // AccessibleContext containing AccessibleHypertext + jint rLinkCount; // link count return value + } GetAccessibleHyperlinkCountPackage; + + // struct for sending a message to get the hypertext for an AccessibleContext + // starting at a specified index in the document + typedef struct GetAccessibleHypertextExtPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // AccessibleContext with hypertext + jint startIndex; // start index in document + AccessibleHypertextInfo rAccessibleHypertextInfo; // returned hypertext + BOOL rSuccess; // whether call succeeded + } GetAccessibleHypertextExtPackage; + + // struct for sending a message to get the nth hyperlink in a document; + // maps to AccessibleHypertext.getLink + typedef struct GetAccessibleHyperlinkPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 hypertext; // AccessibleHypertext + jint linkIndex; // hyperlink index + AccessibleHyperlinkInfo rAccessibleHyperlinkInfo; // returned hyperlink + } GetAccessibleHyperlinkPackage; + + // struct for sending a message to get the index into an array + // of hyperlinks that is associated with a character index in a + // document; maps to AccessibleHypertext.getLinkIndex + typedef struct GetAccessibleHypertextLinkIndexPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 hypertext; // AccessibleHypertext + jint charIndex; // character index in document + jint rLinkIndex; // returned hyperlink index + } GetAccessibleHypertextLinkIndexPackage; + + /** + ****************************************************** + * Accessible Key Bindings packages + ****************************************************** + */ + +#define MAX_KEY_BINDINGS 10 + + // keyboard character modifiers +#define ACCESSIBLE_SHIFT_KEYSTROKE 1 +#define ACCESSIBLE_CONTROL_KEYSTROKE 2 +#define ACCESSIBLE_META_KEYSTROKE 4 +#define ACCESSIBLE_ALT_KEYSTROKE 8 +#define ACCESSIBLE_ALT_GRAPH_KEYSTROKE 16 +#define ACCESSIBLE_BUTTON1_KEYSTROKE 32 +#define ACCESSIBLE_BUTTON2_KEYSTROKE 64 +#define ACCESSIBLE_BUTTON3_KEYSTROKE 128 +#define ACCESSIBLE_FKEY_KEYSTROKE 256 // F key pressed, character contains 1-24 +#define ACCESSIBLE_CONTROLCODE_KEYSTROKE 512 // Control code key pressed, character contains control code. + +// The supported control code keys are: +#define ACCESSIBLE_VK_BACK_SPACE 8 +#define ACCESSIBLE_VK_DELETE 127 +#define ACCESSIBLE_VK_DOWN 40 +#define ACCESSIBLE_VK_END 35 +#define ACCESSIBLE_VK_HOME 36 +#define ACCESSIBLE_VK_INSERT 155 +#define ACCESSIBLE_VK_KP_DOWN 225 +#define ACCESSIBLE_VK_KP_LEFT 226 +#define ACCESSIBLE_VK_KP_RIGHT 227 +#define ACCESSIBLE_VK_KP_UP 224 +#define ACCESSIBLE_VK_LEFT 37 +#define ACCESSIBLE_VK_PAGE_DOWN 34 +#define ACCESSIBLE_VK_PAGE_UP 33 +#define ACCESSIBLE_VK_RIGHT 39 +#define ACCESSIBLE_VK_UP 38 + + // a key binding associates with a component + typedef struct AccessibleKeyBindingInfoTag { + jchar character; // the key character + jint modifiers; // the key modifiers + } AccessibleKeyBindingInfo; + + // all of the key bindings associated with a component + typedef struct AccessibleKeyBindingsTag { + int keyBindingsCount; // number of key bindings + AccessibleKeyBindingInfo keyBindingInfo[MAX_KEY_BINDINGS]; + } AccessibleKeyBindings; + + // struct to get the key bindings associated with a component + typedef struct GetAccessibleKeyBindingsPackageTag { + long vmID; // the virtual machine id + JOBJECT64 accessibleContext; // the component + AccessibleKeyBindings rAccessibleKeyBindings; // the key bindings + } GetAccessibleKeyBindingsPackage; + + /** +****************************************************** +* AccessibleIcon packages +****************************************************** +*/ +#define MAX_ICON_INFO 8 + + // an icon assocated with a component + typedef struct AccessibleIconInfoTag { + wchar_t description[SHORT_STRING_SIZE]; // icon description + jint height; // icon height + jint width; // icon width + } AccessibleIconInfo; + + // all of the icons associated with a component + typedef struct AccessibleIconsTag { + jint iconsCount; // number of icons + AccessibleIconInfo iconInfo[MAX_ICON_INFO]; // the icons + } AccessibleIcons; + + // struct to get the icons associated with a component + typedef struct GetAccessibleIconsPackageTag { + long vmID; // the virtual machine id + JOBJECT64 accessibleContext; // the component + AccessibleIcons rAccessibleIcons; // the icons + } GetAccessibleIconsPackage; + + + /** +****************************************************** +* AccessibleAction packages +****************************************************** +*/ +#define MAX_ACTION_INFO 256 +#define MAX_ACTIONS_TO_DO 32 + + // an action assocated with a component + typedef struct AccessibleActionInfoTag { + wchar_t name[SHORT_STRING_SIZE]; // action name + } AccessibleActionInfo; + + // all of the actions associated with a component + typedef struct AccessibleActionsTag { + jint actionsCount; // number of actions + AccessibleActionInfo actionInfo[MAX_ACTION_INFO]; // the action information + } AccessibleActions; + + // struct for requesting the actions associated with a component + typedef struct GetAccessibleActionsPackageTag { + long vmID; + JOBJECT64 accessibleContext; // the component + AccessibleActions rAccessibleActions; // the actions + } GetAccessibleActionsPackage; + + // list of AccessibleActions to do + typedef struct AccessibleActionsToDoTag { + jint actionsCount; // number of actions to do + AccessibleActionInfo actions[MAX_ACTIONS_TO_DO];// the accessible actions to do + } AccessibleActionsToDo; + + // struct for sending an message to do one or more actions + typedef struct DoAccessibleActionsPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // component to do the action + AccessibleActionsToDo actionsToDo; // the accessible actions to do + BOOL rResult; // action return value + jint failure; // index of action that failed if rResult is FALSE + } DoAccessibleActionsPackage; + + /** +****************************************************** +* AccessibleText packages +****************************************************** +*/ + + typedef struct GetAccessibleTextInfoPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint x; + jint y; + AccessibleTextInfo rTextInfo; + } GetAccessibleTextInfoPackage; + + typedef struct GetAccessibleTextItemsPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + AccessibleTextItemsInfo rTextItemsInfo; + } GetAccessibleTextItemsPackage; + + typedef struct GetAccessibleTextSelectionInfoPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + AccessibleTextSelectionInfo rTextSelectionItemsInfo; + } GetAccessibleTextSelectionInfoPackage; + + typedef struct GetAccessibleTextAttributeInfoPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + AccessibleTextAttributesInfo rAttributeInfo; + } GetAccessibleTextAttributeInfoPackage; + + typedef struct GetAccessibleTextRectInfoPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + AccessibleTextRectInfo rTextRectInfo; + } GetAccessibleTextRectInfoPackage; + + typedef struct GetCaretLocationPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + AccessibleTextRectInfo rTextRectInfo; + } GetCaretLocationPackage; + + typedef struct GetAccessibleTextLineBoundsPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + jint rLineStart; + jint rLineEnd; + } GetAccessibleTextLineBoundsPackage; + + typedef struct GetAccessibleTextRangePackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint start; + jint end; + wchar_t rText[MAX_BUFFER_SIZE]; + } GetAccessibleTextRangePackage; + + /** +****************************************************** +* +* Utility method packages +****************************************************** +*/ + + typedef struct SetTextContentsPackageTag { + long vmID; + JOBJECT64 accessibleContext; // the text field + wchar_t text[MAX_STRING_SIZE]; // the text + BOOL rResult; + } SetTextContentsPackage; + + typedef struct GetParentWithRolePackageTag { + long vmID; + JOBJECT64 accessibleContext; + wchar_t role[SHORT_STRING_SIZE]; // one of Accessible Roles above + JOBJECT64 rAccessibleContext; + } GetParentWithRolePackage; + + typedef struct GetTopLevelObjectPackageTag { + long vmID; + JOBJECT64 accessibleContext; + JOBJECT64 rAccessibleContext; + } GetTopLevelObjectPackage; + + typedef struct GetParentWithRoleElseRootPackageTag { + long vmID; + JOBJECT64 accessibleContext; + wchar_t role[SHORT_STRING_SIZE]; // one of Accessible Roles above + JOBJECT64 rAccessibleContext; + } GetParentWithRoleElseRootPackage; + + typedef struct GetObjectDepthPackageTag { + long vmID; + JOBJECT64 accessibleContext; + jint rResult; + } GetObjectDepthPackage; + + typedef struct GetActiveDescendentPackageTag { + long vmID; + JOBJECT64 accessibleContext; + JOBJECT64 rAccessibleContext; + } GetActiveDescendentPackage; + + /** +****************************************************** +* AccessibleValue packages +****************************************************** +*/ + + typedef struct GetCurrentAccessibleValueFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + wchar_t rValue[SHORT_STRING_SIZE]; + } GetCurrentAccessibleValueFromContextPackage; + + typedef struct GetMaximumAccessibleValueFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + wchar_t rValue[SHORT_STRING_SIZE]; + } GetMaximumAccessibleValueFromContextPackage; + + typedef struct GetMinimumAccessibleValueFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + wchar_t rValue[SHORT_STRING_SIZE]; + } GetMinimumAccessibleValueFromContextPackage; + + + /** +****************************************************** +* AccessibleSelection packages +****************************************************** +*/ + + typedef struct AddAccessibleSelectionFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + } AddAccessibleSelectionFromContextPackage; + + typedef struct ClearAccessibleSelectionFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + } ClearAccessibleSelectionFromContextPackage; + + typedef struct GetAccessibleSelectionFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + JOBJECT64 rAccessibleContext; + } GetAccessibleSelectionFromContextPackage; + + typedef struct GetAccessibleSelectionCountFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint rCount; + } GetAccessibleSelectionCountFromContextPackage; + + typedef struct IsAccessibleChildSelectedFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + jboolean rResult; + } IsAccessibleChildSelectedFromContextPackage; + + typedef struct RemoveAccessibleSelectionFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + jint index; + } RemoveAccessibleSelectionFromContextPackage; + + typedef struct SelectAllAccessibleSelectionFromContextPackageTag { + long vmID; + JOBJECT64 AccessibleContext; + } SelectAllAccessibleSelectionFromContextPackage; + + + /** +****************************************************** +* Java Event Notification Registration packages +****************************************************** +*/ + + typedef struct AddJavaEventNotificationPackageTag { + jlong type; + //HWND DLLwindow; + ABHWND64 DLLwindow; + } AddJavaEventNotificationPackage; + + typedef struct RemoveJavaEventNotificationPackageTag { + jlong type; + //HWND DLLwindow; + ABHWND64 DLLwindow; + } RemoveJavaEventNotificationPackage; + + + /** +****************************************************** +* Accessibility Event Notification Registration packages +****************************************************** +*/ + + typedef struct AddAccessibilityEventNotificationPackageTag { + jlong type; + //HWND DLLwindow; + ABHWND64 DLLwindow; + } AddAccessibilityEventNotificationPackage; + + typedef struct RemoveAccessibilityEventNotificationPackageTag { + jlong type; + //HWND DLLwindow; + ABHWND64 DLLwindow; + } RemoveAccessibilityEventNotificationPackage; + + + /** +****************************************************** +* Accessibility Property Change Event packages +****************************************************** +*/ + + typedef struct PropertyCaretChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + jint oldPosition; + jint newPosition; + } PropertyCaretChangePackage; + + typedef struct PropertyDescriptionChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + wchar_t oldDescription[SHORT_STRING_SIZE]; + wchar_t newDescription[SHORT_STRING_SIZE]; + } PropertyDescriptionChangePackage; + + typedef struct PropertyNameChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + wchar_t oldName[SHORT_STRING_SIZE]; + wchar_t newName[SHORT_STRING_SIZE]; + } PropertyNameChangePackage; + + typedef struct PropertySelectionChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } PropertySelectionChangePackage; + + typedef struct PropertyStateChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + wchar_t oldState[SHORT_STRING_SIZE]; + wchar_t newState[SHORT_STRING_SIZE]; + } PropertyStateChangePackage; + + typedef struct PropertyTextChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } PropertyTextChangePackage; + + typedef struct PropertyValueChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + wchar_t oldValue[SHORT_STRING_SIZE]; + wchar_t newValue[SHORT_STRING_SIZE]; + } PropertyValueChangePackage; + + typedef struct PropertyVisibleDataChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } PropertyVisibleDataChangePackage; + + typedef struct PropertyChildChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + JOBJECT64 oldChildAccessibleContext; + JOBJECT64 newChildAccessibleContext; + } PropertyChildChangePackage; + + typedef struct PropertyActiveDescendentChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + JOBJECT64 oldActiveDescendentAccessibleContext; + JOBJECT64 newActiveDescendentAccessibleContext; + } PropertyActiveDescendentChangePackage; + + + // String format for newValue is: + // "type" one of "INSERT", "UPDATE" or "DELETE" + // "firstRow" + // "lastRow" + // "firstColumn" + // "lastColumn" + // + // oldValue is currently unused + // + typedef struct PropertyTableModelChangePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + wchar_t oldValue[SHORT_STRING_SIZE]; + wchar_t newValue[SHORT_STRING_SIZE]; + } PropertyTableModelChangePackage; + + + /** +****************************************************** +* Property Change Event packages +****************************************************** +*/ + + /* + typedef struct PropertyChangePackageTag { + long vmID; + jobject Event; + jobject AccessibleContextSource; + char propertyName[SHORT_STRING_SIZE]; + char oldValue[SHORT_STRING_SIZE]; // PropertyChangeEvent().getOldValue().toString() + char newValue[SHORT_STRING_SIZE]; // PropertyChangeEvent().getNewValue().toString() + } PropertyChangePackage; + */ + + /* + * Java shutdown event package + */ + typedef struct JavaShutdownPackageTag { + long vmID; + } JavaShutdownPackage; + + + /** +****************************************************** +* Focus Event packages +****************************************************** +*/ + + typedef struct FocusGainedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } FocusGainedPackage; + + typedef struct FocusLostPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } FocusLostPackage; + + + /** +****************************************************** +* Caret Event packages +****************************************************** +*/ + + typedef struct CaretUpdatePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } CaretUpdatePackage; + + + /** +****************************************************** +* Mouse Event packages +****************************************************** +*/ + + typedef struct MouseClickedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MouseClickedPackage; + + typedef struct MouseEnteredPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MouseEnteredPackage; + + typedef struct MouseExitedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MouseExitedPackage; + + typedef struct MousePressedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MousePressedPackage; + + typedef struct MouseReleasedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MouseReleasedPackage; + + + /** +****************************************************** +* Menu/PopupMenu Event packages +****************************************************** +*/ + + typedef struct MenuCanceledPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MenuCanceledPackage; + + typedef struct MenuDeselectedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MenuDeselectedPackage; + + typedef struct MenuSelectedPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } MenuSelectedPackage; + + + typedef struct PopupMenuCanceledPackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } PopupMenuCanceledPackage; + + typedef struct PopupMenuWillBecomeInvisiblePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } PopupMenuWillBecomeInvisiblePackage; + + typedef struct PopupMenuWillBecomeVisiblePackageTag { + long vmID; + JOBJECT64 Event; + JOBJECT64 AccessibleContextSource; + } PopupMenuWillBecomeVisiblePackage; + + /** +****************************************************** +* Additional methods for Teton +****************************************************** +*/ + + /** + * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns + * whether successful. + * + * Bug ID 4916682 - Implement JAWS AccessibleName policy + */ + typedef struct GetVirtualAccessibleNamePackageTag { + long vmID; + AccessibleContext accessibleContext; + wchar_t rName[MAX_STRING_SIZE]; + int len; + } GetVirtualAccessibleNamePackage; + + /** + * Request focus for a component. Returns whether successful; + * + * Bug ID 4944757 - requestFocus method needed + */ + typedef struct RequestFocusPackageTag { + long vmID; + AccessibleContext accessibleContext; + } RequestFocusPackage; + + /** + * Selects text between two indices. Selection includes the text at the start index + * and the text at the end index. Returns whether successful; + * + * Bug ID 4944758 - selectTextRange method needed + */ + typedef struct SelectTextRangePackageTag { + long vmID; + AccessibleContext accessibleContext; + jint startIndex; + jint endIndex; + } SelectTextRangePackage; + + /** + * Gets the number of contiguous characters with the same attributes. + * + * Bug ID 4944761 - getTextAttributes between two indices method needed + */ + typedef struct GetTextAttributesInRangePackageTag { + long vmID; + AccessibleContext accessibleContext; + jint startIndex; // start index (inclusive) + jint endIndex; // end index (inclusive) + AccessibleTextAttributesInfo attributes; // character attributes to match + short rLength; // number of contiguous characters with matching attributes + } GetTextAttributesInRangePackage; + +#define MAX_VISIBLE_CHILDREN 256 + + // visible children information + typedef struct VisibleChildenInfoTag { + int returnedChildrenCount; // number of children returned + AccessibleContext children[MAX_VISIBLE_CHILDREN]; // the visible children + } VisibleChildrenInfo; + + // struct for sending a message to get the number of visible children + typedef struct GetVisibleChildrenCountPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // AccessibleContext of parent component + jint rChildrenCount; // visible children count return value + } GetVisibleChildrenCountPackage; + + // struct for sending a message to get the hypertext for an AccessibleContext + // starting at a specified index in the document + typedef struct GetVisibleChildrenPackageTag { + long vmID; // the virtual machine ID + JOBJECT64 accessibleContext; // AccessibleContext of parent component + jint startIndex; // start index for retrieving children + VisibleChildrenInfo rVisibleChildrenInfo; // returned info + BOOL rSuccess; // whether call succeeded + } GetVisibleChildrenPackage; + + /** + * Set the caret to a text position. Returns whether successful; + * + * Bug ID 4944770 - setCaretPosition method needed + */ + typedef struct SetCaretPositionPackageTag { + long vmID; + AccessibleContext accessibleContext; + jint position; + } SetCaretPositionPackage; + + + /** + ****************************************************** + * Wrapping up all of the packages + ****************************************************** + */ + + /** + * What is the type of this package + */ + typedef enum PackageType { + + cMemoryMappedFileCreatedPackage = 0x11000, + + // many of these will go away... + cJavaVMCreatedPackage = 0x10000, + cJavaVMDestroyedPackage, + cWindowsATCreatedPackage, + cWindowsATDestroyedPackage, + cJavaVMPresentNotificationPackage, + cWindowsATPresentNotificationPackage, + + cReleaseJavaObjectPackage = 1, + cGetAccessBridgeVersionPackage = 2, + + cGetAccessibleContextFromHWNDPackage = 0x10, + cIsJavaWindowPackage, + cGetHWNDFromAccessibleContextPackage, + + cGetAccessibleContextAtPackage = 0x100, + cGetAccessibleContextWithFocusPackage, + cGetAccessibleContextInfoPackage, + cGetAccessibleChildFromContextPackage, + cGetAccessibleParentFromContextPackage, + cIsSameObjectPackage, + + cGetAccessibleTextInfoPackage = 0x200, + cGetAccessibleTextItemsPackage, + cGetAccessibleTextSelectionInfoPackage, + cGetAccessibleTextAttributeInfoPackage, + cGetAccessibleTextRectInfoPackage, + cGetAccessibleTextLineBoundsPackage, + cGetAccessibleTextRangePackage, + + cGetCurrentAccessibleValueFromContextPackage = 0x300, + cGetMaximumAccessibleValueFromContextPackage, + cGetMinimumAccessibleValueFromContextPackage, + + cAddAccessibleSelectionFromContextPackage = 0x400, + cClearAccessibleSelectionFromContextPackage, + cGetAccessibleSelectionFromContextPackage, + cGetAccessibleSelectionCountFromContextPackage, + cIsAccessibleChildSelectedFromContextPackage, + cRemoveAccessibleSelectionFromContextPackage, + cSelectAllAccessibleSelectionFromContextPackage, + + cAddJavaEventNotificationPackage = 0x900, + cRemoveJavaEventNotificationPackage, + cAddAccessibilityEventNotificationPackage, + cRemoveAccessibilityEventNotificationPackage, + + cPropertyChangePackage = 0x1000, + + cJavaShutdownPackage = 0x1010, + cFocusGainedPackage, + cFocusLostPackage, + + cCaretUpdatePackage = 0x1020, + + cMouseClickedPackage = 0x1030, + cMouseEnteredPackage, + cMouseExitedPackage, + cMousePressedPackage, + cMouseReleasedPackage, + + cMenuCanceledPackage = 0x1040, + cMenuDeselectedPackage, + cMenuSelectedPackage, + cPopupMenuCanceledPackage, + cPopupMenuWillBecomeInvisiblePackage, + cPopupMenuWillBecomeVisiblePackage, + + cPropertyCaretChangePackage = 0x1100, + cPropertyDescriptionChangePackage, + cPropertyNameChangePackage, + cPropertySelectionChangePackage, + cPropertyStateChangePackage, + cPropertyTextChangePackage, + cPropertyValueChangePackage, + cPropertyVisibleDataChangePackage, + cPropertyChildChangePackage, + cPropertyActiveDescendentChangePackage, + + + // AccessibleTable + cGetAccessibleTableInfoPackage = 0x1200, + cGetAccessibleTableCellInfoPackage, + + cGetAccessibleTableRowHeaderPackage, + cGetAccessibleTableColumnHeaderPackage, + + cGetAccessibleTableRowDescriptionPackage, + cGetAccessibleTableColumnDescriptionPackage, + + cGetAccessibleTableRowSelectionCountPackage, + cIsAccessibleTableRowSelectedPackage, + cGetAccessibleTableRowSelectionsPackage, + + cGetAccessibleTableColumnSelectionCountPackage, + cIsAccessibleTableColumnSelectedPackage, + cGetAccessibleTableColumnSelectionsPackage, + + cGetAccessibleTableRowPackage, + cGetAccessibleTableColumnPackage, + cGetAccessibleTableIndexPackage, + + cPropertyTableModelChangePackage, + + + // AccessibleRelationSet + cGetAccessibleRelationSetPackage = 0x1300, + + // AccessibleHypertext + cGetAccessibleHypertextPackage = 0x1400, + cActivateAccessibleHyperlinkPackage, + cGetAccessibleHyperlinkCountPackage, + cGetAccessibleHypertextExtPackage, + cGetAccessibleHypertextLinkIndexPackage, + cGetAccessibleHyperlinkPackage, + + // Accessible KeyBinding, Icon and Action + cGetAccessibleKeyBindingsPackage = 0x1500, + cGetAccessibleIconsPackage, + cGetAccessibleActionsPackage, + cDoAccessibleActionsPackage, + + // Utility methods + cSetTextContentsPackage = 0x1600, + cGetParentWithRolePackage, + cGetTopLevelObjectPackage, + cGetParentWithRoleElseRootPackage, + cGetObjectDepthPackage, + cGetActiveDescendentPackage, + + // Additional methods for Teton + cGetVirtualAccessibleNamePackage = 0x1700, + cRequestFocusPackage, + cSelectTextRangePackage, + cGetTextAttributesInRangePackage, + cGetSameTextAttributesInRangePackage, + cGetVisibleChildrenCountPackage, + cGetVisibleChildrenPackage, + cSetCaretPositionPackage, + cGetCaretLocationPackage + + + } PackageType; + + + /** + * Union of all package contents + */ + typedef union AllPackagesTag { + + // Initial Rendezvous packages + MemoryMappedFileCreatedPackage memoryMappedFileCreatedPackage; + + JavaVMCreatedPackage javaVMCreatedPackage; + JavaVMDestroyedPackage javaVMDestroyedPackage; + WindowsATCreatedPackage windowsATCreatedPackage; + WindowsATDestroyedPackage windowsATDestroyedPackage; + JavaVMPresentNotificationPackage javaVMPresentNotificationPackage; + WindowsATPresentNotificationPackage windowsATPresentNotificationPackage; + + // Core packages + ReleaseJavaObjectPackage releaseJavaObject; + GetAccessBridgeVersionPackage getAccessBridgeVersion; + + // Window packages + GetAccessibleContextFromHWNDPackage getAccessibleContextFromHWND; + GetHWNDFromAccessibleContextPackage getHWNDFromAccessibleContext; + + // AccessibleContext packages + GetAccessibleContextAtPackage getAccessibleContextAt; + GetAccessibleContextWithFocusPackage getAccessibleContextWithFocus; + GetAccessibleContextInfoPackage getAccessibleContextInfo; + GetAccessibleChildFromContextPackage getAccessibleChildFromContext; + GetAccessibleParentFromContextPackage getAccessibleParentFromContext; + + // AccessibleText packages + GetAccessibleTextInfoPackage getAccessibleTextInfo; + GetAccessibleTextItemsPackage getAccessibleTextItems; + GetAccessibleTextSelectionInfoPackage getAccessibleTextSelectionInfo; + GetAccessibleTextAttributeInfoPackage getAccessibleTextAttributeInfo; + GetAccessibleTextRectInfoPackage getAccessibleTextRectInfo; + GetAccessibleTextLineBoundsPackage getAccessibleTextLineBounds; + GetAccessibleTextRangePackage getAccessibleTextRange; + + // AccessibleValue packages + GetCurrentAccessibleValueFromContextPackage getCurrentAccessibleValueFromContext; + GetMaximumAccessibleValueFromContextPackage getMaximumAccessibleValueFromContext; + GetMinimumAccessibleValueFromContextPackage getMinimumAccessibleValueFromContext; + + // AccessibleSelection packages + AddAccessibleSelectionFromContextPackage addAccessibleSelectionFromContext; + ClearAccessibleSelectionFromContextPackage clearAccessibleSelectionFromContext; + GetAccessibleSelectionFromContextPackage getAccessibleSelectionFromContext; + GetAccessibleSelectionCountFromContextPackage getAccessibleSelectionCountFromContext; + IsAccessibleChildSelectedFromContextPackage isAccessibleChildSelectedFromContext; + RemoveAccessibleSelectionFromContextPackage removeAccessibleSelectionFromContext; + SelectAllAccessibleSelectionFromContextPackage selectAllAccessibleSelectionFromContext; + + // Event Notification Registration packages + AddJavaEventNotificationPackage addJavaEventNotification; + RemoveJavaEventNotificationPackage removeJavaEventNotification; + AddAccessibilityEventNotificationPackage addAccessibilityEventNotification; + RemoveAccessibilityEventNotificationPackage removeAccessibilityEventNotification; + + // Event contents packages + // PropertyChangePackage propertyChange; + PropertyCaretChangePackage propertyCaretChangePackage; + PropertyDescriptionChangePackage propertyDescriptionChangePackage; + PropertyNameChangePackage propertyNameChangePackage; + PropertySelectionChangePackage propertySelectionChangePackage; + PropertyStateChangePackage propertyStateChangePackage; + PropertyTextChangePackage propertyTextChangePackage; + PropertyValueChangePackage propertyValueChangePackage; + PropertyVisibleDataChangePackage propertyVisibleDataChangePackage; + PropertyChildChangePackage propertyChildChangePackage; + PropertyActiveDescendentChangePackage propertyActiveDescendentChangePackage; + + PropertyTableModelChangePackage propertyTableModelChangePackage; + + JavaShutdownPackage JavaShutdown; + FocusGainedPackage focusGained; + FocusLostPackage focusLost; + + CaretUpdatePackage caretUpdate; + + MouseClickedPackage mouseClicked; + MouseEnteredPackage mouseEntered; + MouseExitedPackage mouseExited; + MousePressedPackage mousePressed; + MouseReleasedPackage mouseReleased; + + MenuCanceledPackage menuCanceled; + MenuDeselectedPackage menuDeselected; + MenuSelectedPackage menuSelected; + PopupMenuCanceledPackage popupMenuCanceled; + PopupMenuWillBecomeInvisiblePackage popupMenuWillBecomeInvisible; + PopupMenuWillBecomeVisiblePackage popupMenuWillBecomeVisible; + + // AccessibleRelationSet + GetAccessibleRelationSetPackage getAccessibleRelationSet; + + // AccessibleHypertext + GetAccessibleHypertextPackage _getAccessibleHypertext; + ActivateAccessibleHyperlinkPackage _activateAccessibleHyperlink; + GetAccessibleHyperlinkCountPackage _getAccessibleHyperlinkCount; + GetAccessibleHypertextExtPackage _getAccessibleHypertextExt; + GetAccessibleHypertextLinkIndexPackage _getAccessibleHypertextLinkIndex; + GetAccessibleHyperlinkPackage _getAccessibleHyperlink; + + // Accessible KeyBinding, Icon and Action + GetAccessibleKeyBindingsPackage getAccessibleKeyBindings; + GetAccessibleIconsPackage getAccessibleIcons; + GetAccessibleActionsPackage getAccessibleActions; + DoAccessibleActionsPackage doAccessibleActions; + + // utility methods + SetTextContentsPackage _setTextContents; + GetParentWithRolePackage _getParentWithRole; + GetTopLevelObjectPackage _getTopLevelObject; + GetParentWithRoleElseRootPackage _getParentWithRoleElseRoot; + GetObjectDepthPackage _getObjectDepth; + GetActiveDescendentPackage _getActiveDescendent; + + // Additional methods for Teton + GetVirtualAccessibleNamePackage _getVirtualAccessibleName; + RequestFocusPackage _requestFocus; + SelectTextRangePackage _selectTextRange; + GetTextAttributesInRangePackage _getTextAttributesInRange; + GetVisibleChildrenCountPackage _getVisibleChildrenCount; + GetVisibleChildrenPackage _getVisibleChildren; + SetCaretPositionPackage _setCaretPosition; + + } AllPackages; + + + /** + * Union of all Java-initiated package contents + */ + typedef union JavaInitiatedPackagesTag { + + // Initial Rendezvous packages + JavaVMCreatedPackage javaVMCreatedPackage; + JavaVMDestroyedPackage javaVMDestroyedPackage; + JavaVMPresentNotificationPackage javaVMPresentNotificationPackage; + + // Event contents packages + PropertyCaretChangePackage propertyCaretChangePackage; + PropertyDescriptionChangePackage propertyDescriptionChangePackage; + PropertyNameChangePackage propertyNameChangePackage; + PropertySelectionChangePackage propertySelectionChangePackage; + PropertyStateChangePackage propertyStateChangePackage; + PropertyTextChangePackage propertyTextChangePackage; + PropertyValueChangePackage propertyValueChangePackage; + PropertyVisibleDataChangePackage propertyVisibleDataChangePackage; + PropertyChildChangePackage propertyChildChangePackage; + PropertyActiveDescendentChangePackage propertyActiveDescendentChangePackage; + + PropertyTableModelChangePackage propertyTableModelChangePackage; + + JavaShutdownPackage JavaShutdown; + FocusGainedPackage focusGained; + FocusLostPackage focusLost; + + CaretUpdatePackage caretUpdate; + + MouseClickedPackage mouseClicked; + MouseEnteredPackage mouseEntered; + MouseExitedPackage mouseExited; + MousePressedPackage mousePressed; + MouseReleasedPackage mouseReleased; + + MenuCanceledPackage menuCanceled; + MenuDeselectedPackage menuDeselected; + MenuSelectedPackage menuSelected; + PopupMenuCanceledPackage popupMenuCanceled; + PopupMenuWillBecomeInvisiblePackage popupMenuWillBecomeInvisible; + PopupMenuWillBecomeVisiblePackage popupMenuWillBecomeVisible; + + } JavaInitiatedPackages; + + + /** + * Union of all Windows-initiated package contents + */ + typedef union WindowsInitiatedPackagesTag { + + // Initial Rendezvous packages + MemoryMappedFileCreatedPackage memoryMappedFileCreatedPackage; + + WindowsATCreatedPackage windowsATCreatedPackage; + WindowsATDestroyedPackage windowsATDestroyedPackage; + WindowsATPresentNotificationPackage windowsATPresentNotificationPackage; + + // Core packages + ReleaseJavaObjectPackage releaseJavaObject; + GetAccessBridgeVersionPackage getAccessBridgeVersion; + + // Window packages + GetAccessibleContextFromHWNDPackage getAccessibleContextFromHWND; + GetHWNDFromAccessibleContextPackage getHWNDFromAccessibleContext; + + // AccessibleContext packages + GetAccessibleContextAtPackage getAccessibleContextAt; + GetAccessibleContextWithFocusPackage getAccessibleContextWithFocus; + GetAccessibleContextInfoPackage getAccessibleContextInfo; + GetAccessibleChildFromContextPackage getAccessibleChildFromContext; + GetAccessibleParentFromContextPackage getAccessibleParentFromContext; + + // AccessibleText packages + GetAccessibleTextInfoPackage getAccessibleTextInfo; + GetAccessibleTextItemsPackage getAccessibleTextItems; + GetAccessibleTextSelectionInfoPackage getAccessibleTextSelectionInfo; + GetAccessibleTextAttributeInfoPackage getAccessibleTextAttributeInfo; + GetAccessibleTextRectInfoPackage getAccessibleTextRectInfo; + GetAccessibleTextLineBoundsPackage getAccessibleTextLineBounds; + GetAccessibleTextRangePackage getAccessibleTextRange; + + // AccessibleValue packages + GetCurrentAccessibleValueFromContextPackage getCurrentAccessibleValueFromContext; + GetMaximumAccessibleValueFromContextPackage getMaximumAccessibleValueFromContext; + GetMinimumAccessibleValueFromContextPackage getMinimumAccessibleValueFromContext; + + // AccessibleSelection packages + AddAccessibleSelectionFromContextPackage addAccessibleSelectionFromContext; + ClearAccessibleSelectionFromContextPackage clearAccessibleSelectionFromContext; + GetAccessibleSelectionFromContextPackage getAccessibleSelectionFromContext; + GetAccessibleSelectionCountFromContextPackage getAccessibleSelectionCountFromContext; + IsAccessibleChildSelectedFromContextPackage isAccessibleChildSelectedFromContext; + RemoveAccessibleSelectionFromContextPackage removeAccessibleSelectionFromContext; + SelectAllAccessibleSelectionFromContextPackage selectAllAccessibleSelectionFromContext; + + // Event Notification Registration packages + AddJavaEventNotificationPackage addJavaEventNotification; + RemoveJavaEventNotificationPackage removeJavaEventNotification; + AddAccessibilityEventNotificationPackage addAccessibilityEventNotification; + RemoveAccessibilityEventNotificationPackage removeAccessibilityEventNotification; + + // AccessibleTable + GetAccessibleTableInfoPackage _getAccessibleTableInfo; + GetAccessibleTableCellInfoPackage _getAccessibleTableCellInfo; + + GetAccessibleTableRowHeaderPackage _getAccessibleTableRowHeader; + GetAccessibleTableColumnHeaderPackage _getAccessibleTableColumnHeader; + + GetAccessibleTableRowDescriptionPackage _getAccessibleTableRowDescription; + GetAccessibleTableColumnDescriptionPackage _getAccessibleTableColumnDescription; + + GetAccessibleTableRowSelectionCountPackage _getAccessibleTableRowSelectionCount; + IsAccessibleTableRowSelectedPackage _isAccessibleTableRowSelected; + GetAccessibleTableRowSelectionsPackage _getAccessibleTableRowSelections; + + GetAccessibleTableColumnSelectionCountPackage _getAccessibleTableColumnSelectionCount; + IsAccessibleTableColumnSelectedPackage _isAccessibleTableColumnSelected; + GetAccessibleTableColumnSelectionsPackage _getAccessibleTableColumnSelections; + + GetAccessibleTableRowPackage _getAccessibleTableRow; + GetAccessibleTableColumnPackage _getAccessibleTableColumn; + GetAccessibleTableIndexPackage _getAccessibleTableIndex; + + // AccessibleRelationSet + GetAccessibleRelationSetPackage _getAccessibleRelationSet; + + // Accessible KeyBindings, Icons and Actions + GetAccessibleKeyBindingsPackage _getAccessibleKeyBindings; + GetAccessibleIconsPackage _getAccessibleIcons; + GetAccessibleActionsPackage _getAccessibleActions; + DoAccessibleActionsPackage _doAccessibleActions; + + + IsSameObjectPackage _isSameObject; + + // utility methods + SetTextContentsPackage _setTextContents; + GetParentWithRolePackage _getParentWithRole; + GetTopLevelObjectPackage _getTopLevelObject; + GetParentWithRoleElseRootPackage _getParentWithRoleElseRoot; + GetObjectDepthPackage _getObjectDepth; + GetActiveDescendentPackage _getActiveDescendent; + + // Additional methods for Teton + GetVirtualAccessibleNamePackage _getVirtualAccessibleName; + RequestFocusPackage _requestFocus; + SelectTextRangePackage _selectTextRange; + GetTextAttributesInRangePackage _getTextAttributesInRange; + GetVisibleChildrenCountPackage _getVisibleChildrenCount; + GetVisibleChildrenPackage _getVisibleChildren; + SetCaretPositionPackage _setCaretPosition; + + + } WindowsInitiatedPackages; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arthas-beans/src/main/native/head/windows/jawt_md.h b/arthas-beans/src/main/native/head/windows/jawt_md.h new file mode 100755 index 000000000..66e7256a2 --- /dev/null +++ b/arthas-beans/src/main/native/head/windows/jawt_md.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JAWT_MD_H_ +#define _JAVASOFT_JAWT_MD_H_ + +#include +#include "jawt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Win32-specific declarations for AWT native interface. + * See notes in jawt.h for an example of use. + */ +typedef struct jawt_Win32DrawingSurfaceInfo { + /* Native window, DDB, or DIB handle */ + union { + HWND hwnd; + HBITMAP hbitmap; + void* pbits; + }; + /* + * This HDC should always be used instead of the HDC returned from + * BeginPaint() or any calls to GetDC(). + */ + HDC hdc; + HPALETTE hpalette; +} JAWT_Win32DrawingSurfaceInfo; + +#ifdef __cplusplus +} +#endif + +#endif /* !_JAVASOFT_JAWT_MD_H_ */ diff --git a/arthas-beans/src/main/native/head/windows/jni_md.h b/arthas-beans/src/main/native/head/windows/jni_md.h new file mode 100755 index 000000000..38080013b --- /dev/null +++ b/arthas-beans/src/main/native/head/windows/jni_md.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#ifndef _JAVASOFT_JNI_MD_H_ +#define _JAVASOFT_JNI_MD_H_ + +#define JNIEXPORT __declspec(dllexport) +#define JNIIMPORT __declspec(dllimport) +#define JNICALL __stdcall + +typedef long jint; +typedef __int64 jlong; +typedef signed char jbyte; + +#endif /* !_JAVASOFT_JNI_MD_H_ */ diff --git a/arthas-beans/src/main/native/include/com_vdian_vclub_JvmUtils.h b/arthas-beans/src/main/native/include/com_vdian_vclub_JvmUtils.h new file mode 100644 index 000000000..f6557e4fa --- /dev/null +++ b/arthas-beans/src/main/native/include/com_vdian_vclub_JvmUtils.h @@ -0,0 +1,61 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_vdian_vclub_JvmUtils */ + +#ifndef _Included_com_vdian_vclub_JvmUtils +#define _Included_com_vdian_vclub_JvmUtils +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_vdian_vclub_JvmUtils + * Method: check + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_vdian_vclub_JvmUtils_check + (JNIEnv *, jclass); + +/* + * Class: com_vdian_vclub_JvmUtils + * Method: getInstances + * Signature: (Ljava/lang/Class;)Ljava/util/ArrayList; + */ +JNIEXPORT jobject JNICALL Java_com_vdian_vclub_JvmUtils_getInstances + (JNIEnv *, jclass, jclass); + +/* + * Class: com_vdian_vclub_JvmUtils + * Method: sumInstanceSize + * Signature: (Ljava/lang/Class;)J + */ +JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_sumInstanceSize + (JNIEnv *, jclass, jclass); + +/* + * Class: com_vdian_vclub_JvmUtils + * Method: getInstanceSize + * Signature: (Ljava/lang/Object;)J + */ +JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_getInstanceSize + (JNIEnv *, jclass, jobject); + +/* + * Class: com_vdian_vclub_JvmUtils + * Method: countInstances + * Signature: (Ljava/lang/Class;)J + */ +JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_countInstances + (JNIEnv *, jclass, jclass); + +/* + * Class: com_vdian_vclub_JvmUtils + * Method: getAllLoadedClasses + * Signature: ()Ljava/util/ArrayList; + */ +JNIEXPORT jobject JNICALL Java_com_vdian_vclub_JvmUtils_getAllLoadedClasses + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/arthas-beans/src/main/native/src/jni-library.cpp b/arthas-beans/src/main/native/src/jni-library.cpp new file mode 100644 index 000000000..bffd95f80 --- /dev/null +++ b/arthas-beans/src/main/native/src/jni-library.cpp @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include "com_vdian_vclub_JvmUtils.h" + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_vdian_vclub_JvmUtils_check(JNIEnv *env, jclass thisClass) { + return env->NewStringUTF("OK"); +} + +extern "C" +jvmtiEnv *getJvmtiEnv(JNIEnv *env) { + + JavaVM *vm; + env->GetJavaVM(&vm); + + jvmtiEnv *jvmti; + vm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_2); + return jvmti; +} + +extern "C" +jobject createJavaInstance(JNIEnv *env, jclass javaClass) { + //找到java类的构造方法 + jmethodID construct = env->GetMethodID(javaClass, "", "()V"); + //生成java类实例 + return env->NewObject(javaClass, construct, ""); +} + +extern "C" +jlong getClassHashCode(JNIEnv *env, jclass javaClass) { + //找到java类的hashCode方法 + jmethodID hashCodeMethod = env->GetMethodID(javaClass, "hashCode", "()I"); + //生成java类实例 + return env->CallLongMethod(javaClass, hashCodeMethod); +} + +extern "C" +jvmtiIterationControl JNICALL +HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) { + auto *data = static_cast(user_data); + *tag_ptr = *data; + return JVMTI_ITERATION_CONTINUE; +} + +extern "C" +JNIEXPORT jobject JNICALL +Java_com_vdian_vclub_JvmUtils_getInstances(JNIEnv *env, jclass thisClass, jclass klass) { + + jvmtiEnv *jvmti = getJvmtiEnv(env); + + jvmtiCapabilities capabilities = {0}; + capabilities.can_tag_objects = 1; + jvmtiError error = jvmti->AddCapabilities(&capabilities); + if (error) { + printf("ERROR: JVMTI AddCapabilities failed!%u\n", error); + return JNI_FALSE; + } + //这里用hashCode作为标记 + jlong tag = getClassHashCode(env, klass); + error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, + HeapObjectCallback, &tag); + if (error) { + printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); + return JNI_FALSE; + } + + jint count = 0; + jobject *instances; + error = jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL); + if (error) { + printf("ERROR: JVMTI GetObjectsWithTags failed!%u\n", error); + return JNI_FALSE; + } + + //通过其签名找到ArrayList的Class + jclass arrayListClass = env->FindClass("java/util/ArrayList"); + jobject arrayList = createJavaInstance(env, arrayListClass); + jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); + //添加元素到ArrayList实例 + for (int i = 0; i < count; i++) { + env->CallObjectMethod(arrayList, addMethod, instances[i]); + } + return arrayList; +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_com_vdian_vclub_JvmUtils_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass) { + + jvmtiEnv *jvmti = getJvmtiEnv(env); + + jvmtiCapabilities capabilities = {0}; + capabilities.can_tag_objects = 1; + jvmtiError error = jvmti->AddCapabilities(&capabilities); + if (error) { + printf("ERROR: JVMTI AddCapabilities failed!%u\n", error); + return JNI_FALSE; + } + //这里用hashCode作为标记 + jlong tag = getClassHashCode(env, klass); + error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, + HeapObjectCallback, &tag); + if (error) { + printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); + return JNI_FALSE; + } + + jint count = 0; + jobject *instances; + error = jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL); + if (error) { + printf("ERROR: JVMTI GetObjectsWithTags failed!%u\n", error); + return JNI_FALSE; + } + + jlong sum = 0; + for (int i = 0; i < count; i++) { + jlong size = 0; + jvmti->GetObjectSize(instances[i], &size); + sum = sum + size; + } + return sum; +} + +extern "C" +JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_getInstanceSize + (JNIEnv *env, jclass thisClass, jobject instance) { + + jvmtiEnv *jvmti = getJvmtiEnv(env); + + jlong size = -1; + jvmtiError error = jvmti->GetObjectSize(instance, &size); + if (error) { + printf("ERROR: JVMTI GetObjectSize failed!%u\n", error); + return JNI_FALSE; + } + return size; +} + +extern "C" +JNIEXPORT jlong JNICALL +Java_com_vdian_vclub_JvmUtils_countInstances(JNIEnv *env, jclass thisClass, jclass klass) { + + jvmtiEnv *jvmti = getJvmtiEnv(env); + + jvmtiCapabilities capabilities = {0}; + capabilities.can_tag_objects = 1; + jvmtiError error = jvmti->AddCapabilities(&capabilities); + if (error) { + printf("ERROR: JVMTI AddCapabilities failed!%u\n", error); + return JNI_FALSE; + } + //这里用hashCode作为标记 + jlong tag = getClassHashCode(env, klass); + error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, + HeapObjectCallback, &tag); + if (error) { + printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); + return JNI_FALSE; + } + + jint count = 0; + error = jvmti->GetObjectsWithTags(1, &tag, &count, NULL, NULL); + if (error) { + printf("ERROR: JVMTI GetObjectsWithTags failed!%u\n", error); + return JNI_FALSE; + } + return count; +} + +extern "C" +JNIEXPORT jobject JNICALL Java_com_vdian_vclub_JvmUtils_getAllLoadedClasses + (JNIEnv *env, jclass thisClass) { + + jvmtiEnv *jvmti = getJvmtiEnv(env); + + jclass *classes; + jint count = 0; + + jvmtiError error = jvmti->GetLoadedClasses(&count, &classes); + if (error) { + printf("ERROR: JVMTI GetLoadedClasses failed!\n"); + return JNI_FALSE; + } + + //通过其签名找到ArrayList的Class + jclass arrayListClass = env->FindClass("java/util/ArrayList"); + jobject arrayList = createJavaInstance(env, arrayListClass); + jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); + //添加元素到ArrayList实例 + for (int i = 0; i < count; i++) { + env->CallObjectMethod(arrayList, addMethod, classes[i]); + } + return arrayList; +} \ No newline at end of file diff --git a/arthas-beans/src/test/java/com/vdian/vclub/JvmUtilsTest.java b/arthas-beans/src/test/java/com/vdian/vclub/JvmUtilsTest.java new file mode 100644 index 000000000..442995b91 --- /dev/null +++ b/arthas-beans/src/test/java/com/vdian/vclub/JvmUtilsTest.java @@ -0,0 +1,48 @@ +package com.vdian.vclub; + +import org.junit.Test; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +public class JvmUtilsTest { + + /** + * 在我的macbook上运行结果如下 + * allLoadedClasses->1050 + * com.vdian.vclub.JvmUtils@5bb21b69 com.vdian.vclub.JvmUtils@6b9651f3 + * before instances->[com.vdian.vclub.JvmUtils@5bb21b69, com.vdian.vclub.JvmUtils@6b9651f3] + * size->16 + * count->2 + * sum size->32 + * null null + * after instances->[] + */ + @Test + public void test01() { + try { + //调用native方法,获取已加载的类,不包括小类型(如int) + ArrayList> allLoadedClasses = JvmUtils.getAllLoadedClasses(); + System.out.println("allLoadedClasses->" + allLoadedClasses.size()); + + //通过下面的例子,可以看到getInstances(Class klass)拿到的是当前存活的所有对象 + WeakReference weakReference1 = new WeakReference(new JvmUtils()); + WeakReference weakReference2 = new WeakReference(new JvmUtils()); + System.out.println(weakReference1.get() + " " + weakReference2.get()); + ArrayList beforeInstances = JvmUtils.getInstances(JvmUtils.class); + System.out.println("before instances->" + beforeInstances); + System.out.println("size->" + JvmUtils.getInstanceSize(weakReference1.get())); + System.out.println("count->" + JvmUtils.countInstances(JvmUtils.class)); + System.out.println("sum size->" + JvmUtils.sumInstanceSize(JvmUtils.class)); + beforeInstances = null; + + System.gc(); + Thread.sleep(100); + System.out.println(weakReference1.get() + " " + weakReference2.get()); + ArrayList afterInstances = JvmUtils.getInstances(JvmUtils.class); + System.out.println("after instances->" + afterInstances); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/pom.xml b/pom.xml index 96a592214..41d9ff3b9 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,7 @@ testcase site packaging + arthas-beans @@ -216,6 +217,11 @@ zt-zip 1.14 + + org.scijava + native-lib-loader + 2.0.2 + From 52bb8afbee34a617c5a92705df03c6b60fca3192 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Mon, 26 Apr 2021 20:38:25 +0800 Subject: [PATCH 02/31] rename arthas-beans module to arthas-vmtool. #1781 --- {arthas-beans => arthas-vmtool}/README_CN.md | 0 {arthas-beans => arthas-vmtool}/pom.xml | 6 +++--- .../src/main/java/com/vdian/vclub/JvmUtils.java | 0 .../src/main/native/CMakeLists.txt | 0 .../src/main/native/head/classfile_constants.h | 0 {arthas-beans => arthas-vmtool}/src/main/native/head/jawt.h | 0 .../src/main/native/head/jdwpTransport.h | 0 {arthas-beans => arthas-vmtool}/src/main/native/head/jni.h | 0 .../src/main/native/head/jvmti.h | 0 .../src/main/native/head/jvmticmlr.h | 0 .../src/main/native/head/linux/jawt_md.h | 0 .../src/main/native/head/linux/jni_md.h | 0 .../src/main/native/head/macos/jawt_md.h | 0 .../src/main/native/head/macos/jni_md.h | 0 .../src/main/native/head/windows/AccessBridgeCallbacks.h | 0 .../src/main/native/head/windows/AccessBridgeCalls.c | 0 .../src/main/native/head/windows/AccessBridgeCalls.h | 0 .../src/main/native/head/windows/AccessBridgePackages.h | 0 .../src/main/native/head/windows/jawt_md.h | 0 .../src/main/native/head/windows/jni_md.h | 0 .../src/main/native/include/com_vdian_vclub_JvmUtils.h | 0 .../src/main/native/src/jni-library.cpp | 0 .../src/test/java/com/vdian/vclub/JvmUtilsTest.java | 0 pom.xml | 2 +- 24 files changed, 4 insertions(+), 4 deletions(-) rename {arthas-beans => arthas-vmtool}/README_CN.md (100%) rename {arthas-beans => arthas-vmtool}/pom.xml (98%) rename {arthas-beans => arthas-vmtool}/src/main/java/com/vdian/vclub/JvmUtils.java (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/CMakeLists.txt (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/classfile_constants.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/jawt.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/jdwpTransport.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/jni.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/jvmti.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/jvmticmlr.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/linux/jawt_md.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/linux/jni_md.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/macos/jawt_md.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/macos/jni_md.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/windows/AccessBridgeCallbacks.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/windows/AccessBridgeCalls.c (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/windows/AccessBridgeCalls.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/windows/AccessBridgePackages.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/windows/jawt_md.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/head/windows/jni_md.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/include/com_vdian_vclub_JvmUtils.h (100%) rename {arthas-beans => arthas-vmtool}/src/main/native/src/jni-library.cpp (100%) rename {arthas-beans => arthas-vmtool}/src/test/java/com/vdian/vclub/JvmUtilsTest.java (100%) diff --git a/arthas-beans/README_CN.md b/arthas-vmtool/README_CN.md similarity index 100% rename from arthas-beans/README_CN.md rename to arthas-vmtool/README_CN.md diff --git a/arthas-beans/pom.xml b/arthas-vmtool/pom.xml similarity index 98% rename from arthas-beans/pom.xml rename to arthas-vmtool/pom.xml index 51628db14..e6162a87e 100644 --- a/arthas-beans/pom.xml +++ b/arthas-vmtool/pom.xml @@ -9,8 +9,8 @@ ${revision} ../pom.xml - arthas-beans - arthas-beans + arthas-vmtool + arthas-vmtool @@ -105,7 +105,7 @@ - arthas-beans + arthas-vmtool org.apache.maven.plugins diff --git a/arthas-beans/src/main/java/com/vdian/vclub/JvmUtils.java b/arthas-vmtool/src/main/java/com/vdian/vclub/JvmUtils.java similarity index 100% rename from arthas-beans/src/main/java/com/vdian/vclub/JvmUtils.java rename to arthas-vmtool/src/main/java/com/vdian/vclub/JvmUtils.java diff --git a/arthas-beans/src/main/native/CMakeLists.txt b/arthas-vmtool/src/main/native/CMakeLists.txt similarity index 100% rename from arthas-beans/src/main/native/CMakeLists.txt rename to arthas-vmtool/src/main/native/CMakeLists.txt diff --git a/arthas-beans/src/main/native/head/classfile_constants.h b/arthas-vmtool/src/main/native/head/classfile_constants.h similarity index 100% rename from arthas-beans/src/main/native/head/classfile_constants.h rename to arthas-vmtool/src/main/native/head/classfile_constants.h diff --git a/arthas-beans/src/main/native/head/jawt.h b/arthas-vmtool/src/main/native/head/jawt.h similarity index 100% rename from arthas-beans/src/main/native/head/jawt.h rename to arthas-vmtool/src/main/native/head/jawt.h diff --git a/arthas-beans/src/main/native/head/jdwpTransport.h b/arthas-vmtool/src/main/native/head/jdwpTransport.h similarity index 100% rename from arthas-beans/src/main/native/head/jdwpTransport.h rename to arthas-vmtool/src/main/native/head/jdwpTransport.h diff --git a/arthas-beans/src/main/native/head/jni.h b/arthas-vmtool/src/main/native/head/jni.h similarity index 100% rename from arthas-beans/src/main/native/head/jni.h rename to arthas-vmtool/src/main/native/head/jni.h diff --git a/arthas-beans/src/main/native/head/jvmti.h b/arthas-vmtool/src/main/native/head/jvmti.h similarity index 100% rename from arthas-beans/src/main/native/head/jvmti.h rename to arthas-vmtool/src/main/native/head/jvmti.h diff --git a/arthas-beans/src/main/native/head/jvmticmlr.h b/arthas-vmtool/src/main/native/head/jvmticmlr.h similarity index 100% rename from arthas-beans/src/main/native/head/jvmticmlr.h rename to arthas-vmtool/src/main/native/head/jvmticmlr.h diff --git a/arthas-beans/src/main/native/head/linux/jawt_md.h b/arthas-vmtool/src/main/native/head/linux/jawt_md.h similarity index 100% rename from arthas-beans/src/main/native/head/linux/jawt_md.h rename to arthas-vmtool/src/main/native/head/linux/jawt_md.h diff --git a/arthas-beans/src/main/native/head/linux/jni_md.h b/arthas-vmtool/src/main/native/head/linux/jni_md.h similarity index 100% rename from arthas-beans/src/main/native/head/linux/jni_md.h rename to arthas-vmtool/src/main/native/head/linux/jni_md.h diff --git a/arthas-beans/src/main/native/head/macos/jawt_md.h b/arthas-vmtool/src/main/native/head/macos/jawt_md.h similarity index 100% rename from arthas-beans/src/main/native/head/macos/jawt_md.h rename to arthas-vmtool/src/main/native/head/macos/jawt_md.h diff --git a/arthas-beans/src/main/native/head/macos/jni_md.h b/arthas-vmtool/src/main/native/head/macos/jni_md.h similarity index 100% rename from arthas-beans/src/main/native/head/macos/jni_md.h rename to arthas-vmtool/src/main/native/head/macos/jni_md.h diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgeCallbacks.h b/arthas-vmtool/src/main/native/head/windows/AccessBridgeCallbacks.h similarity index 100% rename from arthas-beans/src/main/native/head/windows/AccessBridgeCallbacks.h rename to arthas-vmtool/src/main/native/head/windows/AccessBridgeCallbacks.h diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.c b/arthas-vmtool/src/main/native/head/windows/AccessBridgeCalls.c similarity index 100% rename from arthas-beans/src/main/native/head/windows/AccessBridgeCalls.c rename to arthas-vmtool/src/main/native/head/windows/AccessBridgeCalls.c diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgeCalls.h b/arthas-vmtool/src/main/native/head/windows/AccessBridgeCalls.h similarity index 100% rename from arthas-beans/src/main/native/head/windows/AccessBridgeCalls.h rename to arthas-vmtool/src/main/native/head/windows/AccessBridgeCalls.h diff --git a/arthas-beans/src/main/native/head/windows/AccessBridgePackages.h b/arthas-vmtool/src/main/native/head/windows/AccessBridgePackages.h similarity index 100% rename from arthas-beans/src/main/native/head/windows/AccessBridgePackages.h rename to arthas-vmtool/src/main/native/head/windows/AccessBridgePackages.h diff --git a/arthas-beans/src/main/native/head/windows/jawt_md.h b/arthas-vmtool/src/main/native/head/windows/jawt_md.h similarity index 100% rename from arthas-beans/src/main/native/head/windows/jawt_md.h rename to arthas-vmtool/src/main/native/head/windows/jawt_md.h diff --git a/arthas-beans/src/main/native/head/windows/jni_md.h b/arthas-vmtool/src/main/native/head/windows/jni_md.h similarity index 100% rename from arthas-beans/src/main/native/head/windows/jni_md.h rename to arthas-vmtool/src/main/native/head/windows/jni_md.h diff --git a/arthas-beans/src/main/native/include/com_vdian_vclub_JvmUtils.h b/arthas-vmtool/src/main/native/include/com_vdian_vclub_JvmUtils.h similarity index 100% rename from arthas-beans/src/main/native/include/com_vdian_vclub_JvmUtils.h rename to arthas-vmtool/src/main/native/include/com_vdian_vclub_JvmUtils.h diff --git a/arthas-beans/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp similarity index 100% rename from arthas-beans/src/main/native/src/jni-library.cpp rename to arthas-vmtool/src/main/native/src/jni-library.cpp diff --git a/arthas-beans/src/test/java/com/vdian/vclub/JvmUtilsTest.java b/arthas-vmtool/src/test/java/com/vdian/vclub/JvmUtilsTest.java similarity index 100% rename from arthas-beans/src/test/java/com/vdian/vclub/JvmUtilsTest.java rename to arthas-vmtool/src/test/java/com/vdian/vclub/JvmUtilsTest.java diff --git a/pom.xml b/pom.xml index 41d9ff3b9..81ab30d75 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ math-game spy common + arthas-vmtool tunnel-common tunnel-client core @@ -71,7 +72,6 @@ testcase site packaging - arthas-beans From 4f91d181e26c051bb6cc213d18d9471cf0328cd8 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Mon, 26 Apr 2021 21:00:41 +0800 Subject: [PATCH 03/31] rename JvmUtils to Vmtool. #1781 --- arthas-vmtool/pom.xml | 4 -- .../JvmUtils.java => arthas/Vmtool.java} | 37 +++++++---- .../src/main/native/include/arthas_Vmtool.h | 61 +++++++++++++++++++ .../native/include/com_vdian_vclub_JvmUtils.h | 61 ------------------- .../src/main/native/src/jni-library.cpp | 14 ++--- .../src/test/java/arthas/VmtoolTest.java | 57 +++++++++++++++++ .../java/com/vdian/vclub/JvmUtilsTest.java | 48 --------------- 7 files changed, 150 insertions(+), 132 deletions(-) rename arthas-vmtool/src/main/java/{com/vdian/vclub/JvmUtils.java => arthas/Vmtool.java} (65%) create mode 100644 arthas-vmtool/src/main/native/include/arthas_Vmtool.h delete mode 100644 arthas-vmtool/src/main/native/include/com_vdian_vclub_JvmUtils.h create mode 100644 arthas-vmtool/src/test/java/arthas/VmtoolTest.java delete mode 100644 arthas-vmtool/src/test/java/com/vdian/vclub/JvmUtilsTest.java diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index e6162a87e..c13775d75 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -198,10 +198,6 @@ arthas-common ${project.version} - - org.scijava - native-lib-loader - junit junit diff --git a/arthas-vmtool/src/main/java/com/vdian/vclub/JvmUtils.java b/arthas-vmtool/src/main/java/arthas/Vmtool.java similarity index 65% rename from arthas-vmtool/src/main/java/com/vdian/vclub/JvmUtils.java rename to arthas-vmtool/src/main/java/arthas/Vmtool.java index 0f707984a..3430ae95b 100644 --- a/arthas-vmtool/src/main/java/com/vdian/vclub/JvmUtils.java +++ b/arthas-vmtool/src/main/java/arthas/Vmtool.java @@ -1,28 +1,41 @@ -package com.vdian.vclub; - -import com.taobao.arthas.common.AnsiLog; -import org.scijava.nativelib.NativeLoader; +package arthas; import java.util.ArrayList; /** * @author ZhangZiCheng 2021-02-12 + * @author hengyunabc 2021-04-26 * @since 3.5.1 */ -public class JvmUtils { +public class Vmtool { /** * 不要修改jni-lib的名称 */ - private final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; + public final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; - static { - try { - NativeLoader.loadLibrary(JNI_LIBRARY_NAME); - AnsiLog.warn("checkResult->" + check() + ", jni-lib available !"); - } catch (Throwable t) { - AnsiLog.error("load jni-lib failed:" + t.getMessage(), t); + private static Vmtool instance; + + private Vmtool() { + } + + public static Vmtool getInstance() { + return getInstance(null); + } + + public static synchronized Vmtool getInstance(String libPath) { + if (instance != null) { + return instance; } + + if (libPath == null) { + System.loadLibrary(JNI_LIBRARY_NAME); + } else { + System.load(libPath); + } + + instance = new Vmtool(); + return instance; } /** diff --git a/arthas-vmtool/src/main/native/include/arthas_Vmtool.h b/arthas-vmtool/src/main/native/include/arthas_Vmtool.h new file mode 100644 index 000000000..903c47405 --- /dev/null +++ b/arthas-vmtool/src/main/native/include/arthas_Vmtool.h @@ -0,0 +1,61 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class arthas_Vmtool */ + +#ifndef _Included_arthas_Vmtool +#define _Included_arthas_Vmtool +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: arthas_Vmtool + * Method: check + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_arthas_Vmtool_check + (JNIEnv *, jclass); + +/* + * Class: arthas_Vmtool + * Method: getInstances + * Signature: (Ljava/lang/Class;)Ljava/util/ArrayList; + */ +JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getInstances + (JNIEnv *, jclass, jclass); + +/* + * Class: arthas_Vmtool + * Method: sumInstanceSize + * Signature: (Ljava/lang/Class;)J + */ +JNIEXPORT jlong JNICALL Java_arthas_Vmtool_sumInstanceSize + (JNIEnv *, jclass, jclass); + +/* + * Class: arthas_Vmtool + * Method: getInstanceSize + * Signature: (Ljava/lang/Object;)J + */ +JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize + (JNIEnv *, jclass, jobject); + +/* + * Class: arthas_Vmtool + * Method: countInstances + * Signature: (Ljava/lang/Class;)J + */ +JNIEXPORT jlong JNICALL Java_arthas_Vmtool_countInstances + (JNIEnv *, jclass, jclass); + +/* + * Class: arthas_Vmtool + * Method: getAllLoadedClasses + * Signature: ()Ljava/util/ArrayList; + */ +JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/arthas-vmtool/src/main/native/include/com_vdian_vclub_JvmUtils.h b/arthas-vmtool/src/main/native/include/com_vdian_vclub_JvmUtils.h deleted file mode 100644 index f6557e4fa..000000000 --- a/arthas-vmtool/src/main/native/include/com_vdian_vclub_JvmUtils.h +++ /dev/null @@ -1,61 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class com_vdian_vclub_JvmUtils */ - -#ifndef _Included_com_vdian_vclub_JvmUtils -#define _Included_com_vdian_vclub_JvmUtils -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: com_vdian_vclub_JvmUtils - * Method: check - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_com_vdian_vclub_JvmUtils_check - (JNIEnv *, jclass); - -/* - * Class: com_vdian_vclub_JvmUtils - * Method: getInstances - * Signature: (Ljava/lang/Class;)Ljava/util/ArrayList; - */ -JNIEXPORT jobject JNICALL Java_com_vdian_vclub_JvmUtils_getInstances - (JNIEnv *, jclass, jclass); - -/* - * Class: com_vdian_vclub_JvmUtils - * Method: sumInstanceSize - * Signature: (Ljava/lang/Class;)J - */ -JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_sumInstanceSize - (JNIEnv *, jclass, jclass); - -/* - * Class: com_vdian_vclub_JvmUtils - * Method: getInstanceSize - * Signature: (Ljava/lang/Object;)J - */ -JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_getInstanceSize - (JNIEnv *, jclass, jobject); - -/* - * Class: com_vdian_vclub_JvmUtils - * Method: countInstances - * Signature: (Ljava/lang/Class;)J - */ -JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_countInstances - (JNIEnv *, jclass, jclass); - -/* - * Class: com_vdian_vclub_JvmUtils - * Method: getAllLoadedClasses - * Signature: ()Ljava/util/ArrayList; - */ -JNIEXPORT jobject JNICALL Java_com_vdian_vclub_JvmUtils_getAllLoadedClasses - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index bffd95f80..2e81b183c 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -2,11 +2,11 @@ #include #include #include -#include "com_vdian_vclub_JvmUtils.h" +#include "arthas_Vmtool.h" extern "C" JNIEXPORT jstring JNICALL -Java_com_vdian_vclub_JvmUtils_check(JNIEnv *env, jclass thisClass) { +Java_arthas_Vmtool_check(JNIEnv *env, jclass thisClass) { return env->NewStringUTF("OK"); } @@ -47,7 +47,7 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) extern "C" JNIEXPORT jobject JNICALL -Java_com_vdian_vclub_JvmUtils_getInstances(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_Vmtool_getInstances(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -88,7 +88,7 @@ Java_com_vdian_vclub_JvmUtils_getInstances(JNIEnv *env, jclass thisClass, jclass extern "C" JNIEXPORT jlong JNICALL -Java_com_vdian_vclub_JvmUtils_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_Vmtool_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -126,7 +126,7 @@ Java_com_vdian_vclub_JvmUtils_sumInstanceSize(JNIEnv *env, jclass thisClass, jcl } extern "C" -JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_getInstanceSize +JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize (JNIEnv *env, jclass thisClass, jobject instance) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -142,7 +142,7 @@ JNIEXPORT jlong JNICALL Java_com_vdian_vclub_JvmUtils_getInstanceSize extern "C" JNIEXPORT jlong JNICALL -Java_com_vdian_vclub_JvmUtils_countInstances(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_Vmtool_countInstances(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -172,7 +172,7 @@ Java_com_vdian_vclub_JvmUtils_countInstances(JNIEnv *env, jclass thisClass, jcla } extern "C" -JNIEXPORT jobject JNICALL Java_com_vdian_vclub_JvmUtils_getAllLoadedClasses +JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses (JNIEnv *env, jclass thisClass) { jvmtiEnv *jvmti = getJvmtiEnv(env); diff --git a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java b/arthas-vmtool/src/test/java/arthas/VmtoolTest.java new file mode 100644 index 000000000..915e0d54b --- /dev/null +++ b/arthas-vmtool/src/test/java/arthas/VmtoolTest.java @@ -0,0 +1,57 @@ +package arthas; + +import org.junit.Test; + +import arthas.Vmtool; + +import java.io.File; +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +public class VmtoolTest { + + /** + * 在我的macbook上运行结果如下 + * allLoadedClasses->1050 + * arthas.JvmUtils@5bb21b69 arthas.JvmUtils@6b9651f3 + * before instances->[arthas.JvmUtils@5bb21b69, arthas.JvmUtils@6b9651f3] + * size->16 + * count->2 + * sum size->32 + * null null + * after instances->[] + */ + @Test + public void test01() { + try { + String path = Vmtool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + System.err.println(path); + + String libPath = new File(path, System.mapLibraryName(Vmtool.JNI_LIBRARY_NAME)).getAbsolutePath(); + Vmtool.getInstance(libPath); + + //调用native方法,获取已加载的类,不包括小类型(如int) + ArrayList> allLoadedClasses = Vmtool.getAllLoadedClasses(); + System.out.println("allLoadedClasses->" + allLoadedClasses.size()); + + //通过下面的例子,可以看到getInstances(Class klass)拿到的是当前存活的所有对象 + WeakReference weakReference1 = new WeakReference(new VmtoolTest()); + WeakReference weakReference2 = new WeakReference(new VmtoolTest()); + System.out.println(weakReference1.get() + " " + weakReference2.get()); + ArrayList beforeInstances = Vmtool.getInstances(Vmtool.class); + System.out.println("before instances->" + beforeInstances); + System.out.println("size->" + Vmtool.getInstanceSize(weakReference1.get())); + System.out.println("count->" + Vmtool.countInstances(Vmtool.class)); + System.out.println("sum size->" + Vmtool.sumInstanceSize(Vmtool.class)); + beforeInstances = null; + + System.gc(); + Thread.sleep(100); + System.out.println(weakReference1.get() + " " + weakReference2.get()); + ArrayList afterInstances = Vmtool.getInstances(Vmtool.class); + System.out.println("after instances->" + afterInstances); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/arthas-vmtool/src/test/java/com/vdian/vclub/JvmUtilsTest.java b/arthas-vmtool/src/test/java/com/vdian/vclub/JvmUtilsTest.java deleted file mode 100644 index 442995b91..000000000 --- a/arthas-vmtool/src/test/java/com/vdian/vclub/JvmUtilsTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.vdian.vclub; - -import org.junit.Test; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class JvmUtilsTest { - - /** - * 在我的macbook上运行结果如下 - * allLoadedClasses->1050 - * com.vdian.vclub.JvmUtils@5bb21b69 com.vdian.vclub.JvmUtils@6b9651f3 - * before instances->[com.vdian.vclub.JvmUtils@5bb21b69, com.vdian.vclub.JvmUtils@6b9651f3] - * size->16 - * count->2 - * sum size->32 - * null null - * after instances->[] - */ - @Test - public void test01() { - try { - //调用native方法,获取已加载的类,不包括小类型(如int) - ArrayList> allLoadedClasses = JvmUtils.getAllLoadedClasses(); - System.out.println("allLoadedClasses->" + allLoadedClasses.size()); - - //通过下面的例子,可以看到getInstances(Class klass)拿到的是当前存活的所有对象 - WeakReference weakReference1 = new WeakReference(new JvmUtils()); - WeakReference weakReference2 = new WeakReference(new JvmUtils()); - System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList beforeInstances = JvmUtils.getInstances(JvmUtils.class); - System.out.println("before instances->" + beforeInstances); - System.out.println("size->" + JvmUtils.getInstanceSize(weakReference1.get())); - System.out.println("count->" + JvmUtils.countInstances(JvmUtils.class)); - System.out.println("sum size->" + JvmUtils.sumInstanceSize(JvmUtils.class)); - beforeInstances = null; - - System.gc(); - Thread.sleep(100); - System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList afterInstances = JvmUtils.getInstances(JvmUtils.class); - System.out.println("after instances->" + afterInstances); - } catch (Exception e) { - e.printStackTrace(); - } - } -} From 15f7844b4f848b2f4b23af2a85cedac251c9cff8 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 00:42:48 +0800 Subject: [PATCH 04/31] refactor Vmtool, support singleton, support VMtoolMXBean. #1781 --- .../src/main/java/arthas/VMtoolMXBean.java | 48 +++++++++++++++++++ .../src/main/java/arthas/Vmtool.java | 46 ++++++++++++++---- .../src/main/native/include/arthas_Vmtool.h | 2 +- .../src/main/native/src/jni-library.cpp | 12 ++--- .../src/test/java/arthas/VmtoolTest.java | 14 +++--- 5 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java diff --git a/arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java b/arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java new file mode 100644 index 000000000..537a081a0 --- /dev/null +++ b/arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java @@ -0,0 +1,48 @@ +package arthas; + +import java.util.ArrayList; + +/** + * VMtool interface for JMX server. How to register VMtool MBean: + * + *
+ * {@code
+ *     ManagementFactory.getPlatformMBeanServer().registerMBean(
+ *             VMtool.getInstance(),
+ *             new ObjectName("arthas:type=VMtool")
+ *     );
+ * }
+ * 
+ * @author hengyunabc 2021-04-26 + */ +public interface VMtoolMXBean { + /** + * 检测jni-lib是否正常,如果正常,应该输出OK + */ + public String check(); + + /** + * 获取某个class在jvm中当前所有存活实例 + */ + public ArrayList getInstances(Class klass); + + /** + * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte + */ + public long sumInstanceSize(Class klass); + + /** + * 获取某个实例的占用内存,单位:Byte + */ + public long getInstanceSize(Object instance); + + /** + * 统计某个class在jvm中当前所有存活实例的总个数 + */ + public long countInstances(Class klass); + + /** + * 获取所有已加载的类 + */ + public ArrayList> getAllLoadedClasses(); +} diff --git a/arthas-vmtool/src/main/java/arthas/Vmtool.java b/arthas-vmtool/src/main/java/arthas/Vmtool.java index 3430ae95b..1f0c21ab3 100644 --- a/arthas-vmtool/src/main/java/arthas/Vmtool.java +++ b/arthas-vmtool/src/main/java/arthas/Vmtool.java @@ -7,7 +7,7 @@ import java.util.ArrayList; * @author hengyunabc 2021-04-26 * @since 3.5.1 */ -public class Vmtool { +public class Vmtool implements VMtoolMXBean { /** * 不要修改jni-lib的名称 @@ -41,39 +41,69 @@ public class Vmtool { /** * 检测jni-lib是否正常,如果正常,应该输出OK */ - public static native String check(); + private static native String check0(); /** * 获取某个class在jvm中当前所有存活实例 */ - public static native ArrayList getInstances(Class klass); + private static native ArrayList getInstances0(Class klass); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte */ - public static native long sumInstanceSize(Class klass); + private static native long sumInstanceSize0(Class klass); /** * 获取某个实例的占用内存,单位:Byte */ - public static native long getInstanceSize(Object instance); + private static native long getInstanceSize0(Object instance); /** * 统计某个class在jvm中当前所有存活实例的总个数 */ - public static native long countInstances(Class klass); + private static native long countInstances0(Class klass); /** * 获取所有已加载的类 */ - public static native ArrayList> getAllLoadedClasses(); + private static native ArrayList> getAllLoadedClasses0(); /** * 包括小类型(如int) */ @SuppressWarnings("all") public static ArrayList getAllClasses() { - return getInstances(Class.class); + return getInstances0(Class.class); + } + + @Override + public String check() { + return check0(); + } + + @Override + public ArrayList getInstances(Class klass) { + return getInstances0(klass); + } + + @Override + public long sumInstanceSize(Class klass) { + return sumInstanceSize0(klass); + } + + @Override + public long getInstanceSize(Object instance) { + return getInstanceSize0(instance); + } + + @Override + public long countInstances(Class klass) { + return countInstances0(klass); + } + + @Override + public ArrayList> getAllLoadedClasses() { + return getAllLoadedClasses0(); } } diff --git a/arthas-vmtool/src/main/native/include/arthas_Vmtool.h b/arthas-vmtool/src/main/native/include/arthas_Vmtool.h index 903c47405..2d03330c5 100644 --- a/arthas-vmtool/src/main/native/include/arthas_Vmtool.h +++ b/arthas-vmtool/src/main/native/include/arthas_Vmtool.h @@ -12,7 +12,7 @@ extern "C" { * Method: check * Signature: ()Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_arthas_Vmtool_check +JNIEXPORT jstring JNICALL Java_arthas_Vmtool_check0 (JNIEnv *, jclass); /* diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 2e81b183c..d140541a5 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -6,7 +6,7 @@ extern "C" JNIEXPORT jstring JNICALL -Java_arthas_Vmtool_check(JNIEnv *env, jclass thisClass) { +Java_arthas_Vmtool_check0(JNIEnv *env, jclass thisClass) { return env->NewStringUTF("OK"); } @@ -47,7 +47,7 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) extern "C" JNIEXPORT jobject JNICALL -Java_arthas_Vmtool_getInstances(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_Vmtool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -88,7 +88,7 @@ Java_arthas_Vmtool_getInstances(JNIEnv *env, jclass thisClass, jclass klass) { extern "C" JNIEXPORT jlong JNICALL -Java_arthas_Vmtool_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_Vmtool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -126,7 +126,7 @@ Java_arthas_Vmtool_sumInstanceSize(JNIEnv *env, jclass thisClass, jclass klass) } extern "C" -JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize +JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize0 (JNIEnv *env, jclass thisClass, jobject instance) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -142,7 +142,7 @@ JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize extern "C" JNIEXPORT jlong JNICALL -Java_arthas_Vmtool_countInstances(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_Vmtool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -172,7 +172,7 @@ Java_arthas_Vmtool_countInstances(JNIEnv *env, jclass thisClass, jclass klass) { } extern "C" -JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses +JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses0 (JNIEnv *env, jclass thisClass) { jvmtiEnv *jvmti = getJvmtiEnv(env); diff --git a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java b/arthas-vmtool/src/test/java/arthas/VmtoolTest.java index 915e0d54b..fe1592557 100644 --- a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmtoolTest.java @@ -28,27 +28,27 @@ public class VmtoolTest { System.err.println(path); String libPath = new File(path, System.mapLibraryName(Vmtool.JNI_LIBRARY_NAME)).getAbsolutePath(); - Vmtool.getInstance(libPath); + Vmtool vmtool = Vmtool.getInstance(libPath); //调用native方法,获取已加载的类,不包括小类型(如int) - ArrayList> allLoadedClasses = Vmtool.getAllLoadedClasses(); + ArrayList> allLoadedClasses = vmtool.getAllLoadedClasses(); System.out.println("allLoadedClasses->" + allLoadedClasses.size()); //通过下面的例子,可以看到getInstances(Class klass)拿到的是当前存活的所有对象 WeakReference weakReference1 = new WeakReference(new VmtoolTest()); WeakReference weakReference2 = new WeakReference(new VmtoolTest()); System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList beforeInstances = Vmtool.getInstances(Vmtool.class); + ArrayList beforeInstances = vmtool.getInstances(Vmtool.class); System.out.println("before instances->" + beforeInstances); - System.out.println("size->" + Vmtool.getInstanceSize(weakReference1.get())); - System.out.println("count->" + Vmtool.countInstances(Vmtool.class)); - System.out.println("sum size->" + Vmtool.sumInstanceSize(Vmtool.class)); + System.out.println("size->" + vmtool.getInstanceSize(weakReference1.get())); + System.out.println("count->" + vmtool.countInstances(Vmtool.class)); + System.out.println("sum size->" + vmtool.sumInstanceSize(Vmtool.class)); beforeInstances = null; System.gc(); Thread.sleep(100); System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList afterInstances = Vmtool.getInstances(Vmtool.class); + ArrayList afterInstances = vmtool.getInstances(Vmtool.class); System.out.println("after instances->" + afterInstances); } catch (Exception e) { e.printStackTrace(); From 4282bdb762c61a9d1e3b63afb40cf56c19323976 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 17:24:47 +0800 Subject: [PATCH 05/31] add build-vmtool.yaml. --- .github/workflows/build-vmtool.yaml | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/build-vmtool.yaml diff --git a/.github/workflows/build-vmtool.yaml b/.github/workflows/build-vmtool.yaml new file mode 100644 index 000000000..801dc3a6b --- /dev/null +++ b/.github/workflows/build-vmtool.yaml @@ -0,0 +1,55 @@ +name: build vmtool + +on: [push] + +jobs: + linux: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + - name: Build with Maven + run: ./mvnw package + - uses: actions/upload-artifact@v2 + with: + name: Package + path: target/*.jar + + mac: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + - name: Build with Maven + run: ./mvnw package + - uses: actions/upload-artifact@v2 + with: + name: Package + path: target/*.jar + + windows: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + - name: Build with Maven + run: ./mvnw package + - uses: actions/upload-artifact@v2 + with: + name: Package + path: target/*.jar \ No newline at end of file From 5e95d66a98fccee2c0c2af13d527b9ed9855fc75 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 17:35:29 +0800 Subject: [PATCH 06/31] fix testcase in windows --- .../taobao/arthas/core/util/LogUtilTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/src/test/java/com/taobao/arthas/core/util/LogUtilTest.java b/core/src/test/java/com/taobao/arthas/core/util/LogUtilTest.java index 483497395..8cb3d153f 100644 --- a/core/src/test/java/com/taobao/arthas/core/util/LogUtilTest.java +++ b/core/src/test/java/com/taobao/arthas/core/util/LogUtilTest.java @@ -1,6 +1,7 @@ package com.taobao.arthas.core.util; import java.io.File; +import java.io.IOException; import java.net.URISyntaxException; import java.util.Iterator; import java.util.Properties; @@ -72,11 +73,10 @@ public class LogUtilTest { } @Test - public void test_DefaultLogFile() throws URISyntaxException { + public void test_DefaultLogFile() throws URISyntaxException, IOException { Properties properties1 = new Properties(); properties1.put("arthas.home", testResourcesDir); - - String logFile = new File(System.getProperty("user.home"), "logs/arthas/arthas.log").getAbsolutePath(); + String logFile = new File(System.getProperty("user.home"), "logs/arthas/arthas.log").getCanonicalPath(); arthasEnvironment.addLast(new PropertiesPropertySource("test1", properties1)); @@ -95,7 +95,7 @@ public class LogUtilTest { if (appender instanceof RollingFileAppender) { RollingFileAppender fileAppender = (RollingFileAppender) appender; String file = fileAppender.getFile(); - Assertions.assertThat(file).isEqualTo(logFile); + Assertions.assertThat(new File(file).getCanonicalPath()).isEqualTo(logFile); foundFileAppender = true; } } @@ -103,11 +103,11 @@ public class LogUtilTest { } @Test - public void test_ARTHAS_LOG_FILE() throws URISyntaxException { + public void test_ARTHAS_LOG_FILE() throws URISyntaxException, IOException { Properties properties1 = new Properties(); properties1.put("arthas.home", testResourcesDir); - String logFile = new File(tempFolder.getRoot().getAbsoluteFile(), "test.log").getAbsolutePath(); + String logFile = new File(tempFolder.getRoot().getAbsoluteFile(), "test.log").getCanonicalPath(); properties1.put(LogUtil.FILE_NAME_PROPERTY, logFile); arthasEnvironment.addLast(new PropertiesPropertySource("test1", properties1)); @@ -127,7 +127,7 @@ public class LogUtilTest { if (appender instanceof RollingFileAppender) { RollingFileAppender fileAppender = (RollingFileAppender) appender; String file = fileAppender.getFile(); - Assertions.assertThat(file).isEqualTo(logFile); + Assertions.assertThat(new File(file).getCanonicalPath()).isEqualTo(logFile); foundFileAppender = true; } } @@ -135,11 +135,11 @@ public class LogUtilTest { } @Test - public void test_ARTHAS_LOG_PATH() throws URISyntaxException { + public void test_ARTHAS_LOG_PATH() throws URISyntaxException, IOException { Properties properties1 = new Properties(); properties1.put("arthas.home", testResourcesDir); - String logFile = new File(tempFolder.getRoot().getAbsoluteFile(), "arthas.log").getAbsolutePath(); + String logFile = new File(tempFolder.getRoot().getAbsoluteFile(), "arthas.log").getCanonicalPath(); properties1.put(LogUtil.FILE_PATH_PROPERTY, tempFolder.getRoot().getAbsolutePath()); arthasEnvironment.addLast(new PropertiesPropertySource("test1", properties1)); @@ -159,7 +159,7 @@ public class LogUtilTest { if (appender instanceof RollingFileAppender) { RollingFileAppender fileAppender = (RollingFileAppender) appender; String file = fileAppender.getFile(); - Assertions.assertThat(file).isEqualTo(logFile); + Assertions.assertThat(new File(file).getCanonicalPath()).isEqualTo(logFile); foundFileAppender = true; } } From 3a044bc9e0147d9787ba823940173ce0d50d37e8 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 18:33:03 +0800 Subject: [PATCH 07/31] support upload lib --- .github/workflows/build-vmtool.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-vmtool.yaml b/.github/workflows/build-vmtool.yaml index 801dc3a6b..6562283c2 100644 --- a/.github/workflows/build-vmtool.yaml +++ b/.github/workflows/build-vmtool.yaml @@ -17,8 +17,8 @@ jobs: run: ./mvnw package - uses: actions/upload-artifact@v2 with: - name: Package - path: target/*.jar + name: lib + path: arthas-vmtool/target/classes/lib* mac: runs-on: macos-latest @@ -34,8 +34,8 @@ jobs: run: ./mvnw package - uses: actions/upload-artifact@v2 with: - name: Package - path: target/*.jar + name: lib + path: arthas-vmtool/target/classes/lib* windows: runs-on: windows-latest @@ -51,5 +51,5 @@ jobs: run: ./mvnw package - uses: actions/upload-artifact@v2 with: - name: Package - path: target/*.jar \ No newline at end of file + name: lib + path: arthas-vmtool/target/classes/*.dll \ No newline at end of file From 3672c2c7a6434bcf0451e0377350c30615440629 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 19:19:16 +0800 Subject: [PATCH 08/31] update lib name --- arthas-vmtool/pom.xml | 12 +++++----- .../src/main/java/arthas/Vmtool.java | 24 +++++++++++++++++++ .../src/test/java/arthas/VmtoolTest.java | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index c13775d75..f7e8799ea 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -25,7 +25,7 @@ macos -m64 - libArthasJniLibrary.dylib + libArthasJniLibrary-x64.dylib @@ -39,7 +39,7 @@ macos -m64 - libArthasJniLibrary.dylib + libArthasJniLibrary-amd64.dylib @@ -55,7 +55,7 @@ linux -m64 - libArthasJniLibrary.so + libArthasJniLibrary-x64.so @@ -69,7 +69,7 @@ linux -m64 - libArthasJniLibrary.so + libArthasJniLibrary-amd64.so @@ -85,7 +85,7 @@ windows -m64 - ArthasJniLibrary.dll + libArthasJniLibrary-x64.dll @@ -99,7 +99,7 @@ windows -m64 - ArthasJniLibrary.dll + libArthasJniLibrary-amd64.dll diff --git a/arthas-vmtool/src/main/java/arthas/Vmtool.java b/arthas-vmtool/src/main/java/arthas/Vmtool.java index 1f0c21ab3..ad72fa649 100644 --- a/arthas-vmtool/src/main/java/arthas/Vmtool.java +++ b/arthas-vmtool/src/main/java/arthas/Vmtool.java @@ -2,6 +2,8 @@ package arthas; import java.util.ArrayList; +import com.taobao.arthas.common.OSUtils; + /** * @author ZhangZiCheng 2021-02-12 * @author hengyunabc 2021-04-26 @@ -14,6 +16,24 @@ public class Vmtool implements VMtoolMXBean { */ public final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; + private static String libName = null; + static { + if (OSUtils.isMac()) { + libName = "libArthasJniLibrary-x64.dylib"; + } + if (OSUtils.isLinux()) { + libName = "libArthasJniLibrary-x64.so"; + if (OSUtils.isArm32()) { + libName = "libArthasJniLibrary-arm.so"; + } else if (OSUtils.isArm64()) { + libName = "libArthasJniLibrary-aarch64.so"; + } + } + if (OSUtils.isWindows()) { + libName = "libArthasJniLibrary-x64.dll"; + } + } + private static Vmtool instance; private Vmtool() { @@ -38,6 +58,10 @@ public class Vmtool implements VMtoolMXBean { return instance; } + public static String detectLibName() { + return libName; + } + /** * 检测jni-lib是否正常,如果正常,应该输出OK */ diff --git a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java b/arthas-vmtool/src/test/java/arthas/VmtoolTest.java index fe1592557..5a2b63553 100644 --- a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmtoolTest.java @@ -27,7 +27,7 @@ public class VmtoolTest { String path = Vmtool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); System.err.println(path); - String libPath = new File(path, System.mapLibraryName(Vmtool.JNI_LIBRARY_NAME)).getAbsolutePath(); + String libPath = new File(path, Vmtool.detectLibName()).getAbsolutePath(); Vmtool vmtool = Vmtool.getInstance(libPath); //调用native方法,获取已加载的类,不包括小类型(如int) From ba2ed2832335f9a98af188326ae7cdee8d39e997 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 20:01:30 +0800 Subject: [PATCH 09/31] do not use auto in cpp --- arthas-vmtool/src/main/native/src/jni-library.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index d140541a5..adeccfb31 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -40,7 +40,7 @@ jlong getClassHashCode(JNIEnv *env, jclass javaClass) { extern "C" jvmtiIterationControl JNICALL HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) { - auto *data = static_cast(user_data); + jlong *data = static_cast(user_data); *tag_ptr = *data; return JVMTI_ITERATION_CONTINUE; } From 5b9eb89826974b8c342d818427293d0311a9fcbe Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 20:19:26 +0800 Subject: [PATCH 10/31] fix lib arch --- arthas-vmtool/pom.xml | 49 ++++--------------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index f7e8799ea..6f5cc74f7 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -13,9 +13,10 @@ arthas-vmtool + - macos-x86_64 + macos-amd64 mac @@ -28,36 +29,8 @@ libArthasJniLibrary-x64.dylib
- - macos-amd64 - - - mac - amd64 - - - - macos - -m64 - libArthasJniLibrary-amd64.dylib - - - - linux-x86_64 - - - linux - x86_64 - - - - linux - -m64 - libArthasJniLibrary-x64.so - - linux-amd64 @@ -69,25 +42,11 @@ linux -m64 - libArthasJniLibrary-amd64.so + libArthasJniLibrary-x64.so - - windows-x86_64 - - - windows - x86_64 - - - - windows - -m64 - libArthasJniLibrary-x64.dll - - windows-amd64 @@ -99,7 +58,7 @@ windows -m64 - libArthasJniLibrary-amd64.dll + libArthasJniLibrary-x64.dll From b704e7cabd8239b8ff9c8ddd4af27596664f843a Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 27 Apr 2021 20:39:46 +0800 Subject: [PATCH 11/31] rename --- .../java/arthas/{Vmtool.java => VmTool.java} | 12 ++++---- .../{VMtoolMXBean.java => VmToolMXBean.java} | 8 ++--- .../{arthas_Vmtool.h => arthas_VmTool.h} | 30 +++++++++---------- .../src/main/native/src/jni-library.cpp | 14 ++++----- .../{VmtoolTest.java => VmToolTest.java} | 28 ++++++++--------- 5 files changed, 45 insertions(+), 47 deletions(-) rename arthas-vmtool/src/main/java/arthas/{Vmtool.java => VmTool.java} (92%) rename arthas-vmtool/src/main/java/arthas/{VMtoolMXBean.java => VmToolMXBean.java} (83%) rename arthas-vmtool/src/main/native/include/{arthas_Vmtool.h => arthas_VmTool.h} (55%) rename arthas-vmtool/src/test/java/arthas/{VmtoolTest.java => VmToolTest.java} (64%) diff --git a/arthas-vmtool/src/main/java/arthas/Vmtool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java similarity index 92% rename from arthas-vmtool/src/main/java/arthas/Vmtool.java rename to arthas-vmtool/src/main/java/arthas/VmTool.java index ad72fa649..ad15d1271 100644 --- a/arthas-vmtool/src/main/java/arthas/Vmtool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -9,7 +9,7 @@ import com.taobao.arthas.common.OSUtils; * @author hengyunabc 2021-04-26 * @since 3.5.1 */ -public class Vmtool implements VMtoolMXBean { +public class VmTool implements VmToolMXBean { /** * 不要修改jni-lib的名称 @@ -34,16 +34,16 @@ public class Vmtool implements VMtoolMXBean { } } - private static Vmtool instance; + private static VmTool instance; - private Vmtool() { + private VmTool() { } - public static Vmtool getInstance() { + public static VmTool getInstance() { return getInstance(null); } - public static synchronized Vmtool getInstance(String libPath) { + public static synchronized VmTool getInstance(String libPath) { if (instance != null) { return instance; } @@ -54,7 +54,7 @@ public class Vmtool implements VMtoolMXBean { System.load(libPath); } - instance = new Vmtool(); + instance = new VmTool(); return instance; } diff --git a/arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java similarity index 83% rename from arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java rename to arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index 537a081a0..e70a17e7a 100644 --- a/arthas-vmtool/src/main/java/arthas/VMtoolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -3,19 +3,19 @@ package arthas; import java.util.ArrayList; /** - * VMtool interface for JMX server. How to register VMtool MBean: + * VmTool interface for JMX server. How to register VmTool MBean: * *
  * {@code
  *     ManagementFactory.getPlatformMBeanServer().registerMBean(
- *             VMtool.getInstance(),
- *             new ObjectName("arthas:type=VMtool")
+ *             VmTool.getInstance(),
+ *             new ObjectName("arthas:type=VmTool")
  *     );
  * }
  * 
* @author hengyunabc 2021-04-26 */ -public interface VMtoolMXBean { +public interface VmToolMXBean { /** * 检测jni-lib是否正常,如果正常,应该输出OK */ diff --git a/arthas-vmtool/src/main/native/include/arthas_Vmtool.h b/arthas-vmtool/src/main/native/include/arthas_VmTool.h similarity index 55% rename from arthas-vmtool/src/main/native/include/arthas_Vmtool.h rename to arthas-vmtool/src/main/native/include/arthas_VmTool.h index 2d03330c5..87098bfac 100644 --- a/arthas-vmtool/src/main/native/include/arthas_Vmtool.h +++ b/arthas-vmtool/src/main/native/include/arthas_VmTool.h @@ -1,58 +1,58 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class arthas_Vmtool */ +/* Header for class arthas_VmTool */ -#ifndef _Included_arthas_Vmtool -#define _Included_arthas_Vmtool +#ifndef _Included_arthas_VmTool +#define _Included_arthas_VmTool #ifdef __cplusplus extern "C" { #endif /* - * Class: arthas_Vmtool + * Class: arthas_VmTool * Method: check * Signature: ()Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_arthas_Vmtool_check0 +JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0 (JNIEnv *, jclass); /* - * Class: arthas_Vmtool + * Class: arthas_VmTool * Method: getInstances * Signature: (Ljava/lang/Class;)Ljava/util/ArrayList; */ -JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getInstances +JNIEXPORT jobject JNICALL Java_arthas_VmTool_getInstances (JNIEnv *, jclass, jclass); /* - * Class: arthas_Vmtool + * Class: arthas_VmTool * Method: sumInstanceSize * Signature: (Ljava/lang/Class;)J */ -JNIEXPORT jlong JNICALL Java_arthas_Vmtool_sumInstanceSize +JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize (JNIEnv *, jclass, jclass); /* - * Class: arthas_Vmtool + * Class: arthas_VmTool * Method: getInstanceSize * Signature: (Ljava/lang/Object;)J */ -JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize +JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize (JNIEnv *, jclass, jobject); /* - * Class: arthas_Vmtool + * Class: arthas_VmTool * Method: countInstances * Signature: (Ljava/lang/Class;)J */ -JNIEXPORT jlong JNICALL Java_arthas_Vmtool_countInstances +JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances (JNIEnv *, jclass, jclass); /* - * Class: arthas_Vmtool + * Class: arthas_VmTool * Method: getAllLoadedClasses * Signature: ()Ljava/util/ArrayList; */ -JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses +JNIEXPORT jobject JNICALL Java_arthas_VmTool_getAllLoadedClasses (JNIEnv *, jclass); #ifdef __cplusplus diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index adeccfb31..776124cdf 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -2,11 +2,11 @@ #include #include #include -#include "arthas_Vmtool.h" +#include "arthas_VmTool.h" extern "C" JNIEXPORT jstring JNICALL -Java_arthas_Vmtool_check0(JNIEnv *env, jclass thisClass) { +Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { return env->NewStringUTF("OK"); } @@ -47,7 +47,7 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) extern "C" JNIEXPORT jobject JNICALL -Java_arthas_Vmtool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -88,7 +88,7 @@ Java_arthas_Vmtool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { extern "C" JNIEXPORT jlong JNICALL -Java_arthas_Vmtool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -126,7 +126,7 @@ Java_arthas_Vmtool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) } extern "C" -JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize0 +JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 (JNIEnv *env, jclass thisClass, jobject instance) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -142,7 +142,7 @@ JNIEXPORT jlong JNICALL Java_arthas_Vmtool_getInstanceSize0 extern "C" JNIEXPORT jlong JNICALL -Java_arthas_Vmtool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -172,7 +172,7 @@ Java_arthas_Vmtool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) } extern "C" -JNIEXPORT jobject JNICALL Java_arthas_Vmtool_getAllLoadedClasses0 +JNIEXPORT jobject JNICALL Java_arthas_VmTool_getAllLoadedClasses0 (JNIEnv *env, jclass thisClass) { jvmtiEnv *jvmti = getJvmtiEnv(env); diff --git a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java similarity index 64% rename from arthas-vmtool/src/test/java/arthas/VmtoolTest.java rename to arthas-vmtool/src/test/java/arthas/VmToolTest.java index 5a2b63553..223a853b5 100644 --- a/arthas-vmtool/src/test/java/arthas/VmtoolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -2,19 +2,17 @@ package arthas; import org.junit.Test; -import arthas.Vmtool; - import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; -public class VmtoolTest { +public class VmToolTest { /** - * 在我的macbook上运行结果如下 + * macbook上运行结果如下 * allLoadedClasses->1050 - * arthas.JvmUtils@5bb21b69 arthas.JvmUtils@6b9651f3 - * before instances->[arthas.JvmUtils@5bb21b69, arthas.JvmUtils@6b9651f3] + * arthas.VmTool@5bb21b69 arthas.VmTool@6b9651f3 + * before instances->[arthas.VmTool@5bb21b69, arthas.VmTool@6b9651f3] * size->16 * count->2 * sum size->32 @@ -24,31 +22,31 @@ public class VmtoolTest { @Test public void test01() { try { - String path = Vmtool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + String path = VmTool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); System.err.println(path); - String libPath = new File(path, Vmtool.detectLibName()).getAbsolutePath(); - Vmtool vmtool = Vmtool.getInstance(libPath); + String libPath = new File(path, VmTool.detectLibName()).getAbsolutePath(); + VmTool vmtool = VmTool.getInstance(libPath); //调用native方法,获取已加载的类,不包括小类型(如int) ArrayList> allLoadedClasses = vmtool.getAllLoadedClasses(); System.out.println("allLoadedClasses->" + allLoadedClasses.size()); //通过下面的例子,可以看到getInstances(Class klass)拿到的是当前存活的所有对象 - WeakReference weakReference1 = new WeakReference(new VmtoolTest()); - WeakReference weakReference2 = new WeakReference(new VmtoolTest()); + WeakReference weakReference1 = new WeakReference(new VmToolTest()); + WeakReference weakReference2 = new WeakReference(new VmToolTest()); System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList beforeInstances = vmtool.getInstances(Vmtool.class); + ArrayList beforeInstances = vmtool.getInstances(VmTool.class); System.out.println("before instances->" + beforeInstances); System.out.println("size->" + vmtool.getInstanceSize(weakReference1.get())); - System.out.println("count->" + vmtool.countInstances(Vmtool.class)); - System.out.println("sum size->" + vmtool.sumInstanceSize(Vmtool.class)); + System.out.println("count->" + vmtool.countInstances(VmTool.class)); + System.out.println("sum size->" + vmtool.sumInstanceSize(VmTool.class)); beforeInstances = null; System.gc(); Thread.sleep(100); System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList afterInstances = vmtool.getInstances(Vmtool.class); + ArrayList afterInstances = vmtool.getInstances(VmTool.class); System.out.println("after instances->" + afterInstances); } catch (Exception e) { e.printStackTrace(); From 6a102d61b0d1653d84f5200925cdadd734f177ff Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 29 Apr 2021 17:41:47 +0800 Subject: [PATCH 12/31] add OptionCompleteHandler, better complete option --- .../core/shell/cli/CompletionUtils.java | 43 +++++++++++++++++++ .../core/shell/cli/OptionCompleteHandler.java | 12 ++++++ 2 files changed, 55 insertions(+) create mode 100644 core/src/main/java/com/taobao/arthas/core/shell/cli/OptionCompleteHandler.java diff --git a/core/src/main/java/com/taobao/arthas/core/shell/cli/CompletionUtils.java b/core/src/main/java/com/taobao/arthas/core/shell/cli/CompletionUtils.java index b5014a19a..c49e5d125 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/cli/CompletionUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/cli/CompletionUtils.java @@ -355,4 +355,47 @@ public class CompletionUtils { } return false; } + + public static boolean completeOptions(Completion completion, List handlers) { + List tokens = completion.lineTokens(); + /** + *
+         * 比如 ` --name a`,这样子的tokens
+         * 
+ */ + if (tokens.size() >= 3) { + CliToken cliToken_2 = tokens.get(tokens.size() - 2); + CliToken cliToken_3 = tokens.get(tokens.size() - 3); + + if (cliToken_2.isBlank()) { + String token_3 = cliToken_3.value(); + + for (OptionCompleteHandler handler : handlers) { + if (handler.matchName(token_3)) { + return handler.complete(completion); + } + } + } + } + + /** + *
+         * 比如 ` --name `,这样子的tokens
+         * 
+ */ + if (tokens.size() >= 2) { + CliToken cliToken_1 = tokens.get(tokens.size() - 1); + CliToken cliToken_2 = tokens.get(tokens.size() - 2); + if (cliToken_1.isBlank()) { + String token_2 = cliToken_2.value(); + for (OptionCompleteHandler handler : handlers) { + if (handler.matchName(token_2)) { + return handler.complete(completion); + } + } + } + } + + return false; + } } diff --git a/core/src/main/java/com/taobao/arthas/core/shell/cli/OptionCompleteHandler.java b/core/src/main/java/com/taobao/arthas/core/shell/cli/OptionCompleteHandler.java new file mode 100644 index 000000000..48778164f --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/shell/cli/OptionCompleteHandler.java @@ -0,0 +1,12 @@ +package com.taobao.arthas.core.shell.cli; + +/** + * + * @author hengyunabc 2021-04-29 + * + */ +public interface OptionCompleteHandler { + boolean matchName(String token); + + boolean complete(Completion completion); +} From 932340eac6e4957f58c883a45f593e8164ee19dd Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 29 Apr 2021 19:28:44 +0800 Subject: [PATCH 13/31] add vmtool command, part1. #1781 --- .../src/main/java/arthas/VmTool.java | 24 -- .../src/main/java/arthas/package-info.java | 6 + .../src/test/java/arthas/VmToolTest.java | 4 +- .../com/taobao/arthas/common/VmToolUtils.java | 30 ++ .../core/command/BuiltinCommandPack.java | 2 + .../command/monitor200/VmToolCommand.java | 261 ++++++++++++++++++ .../taobao/arthas/core/util/ClassUtils.java | 2 +- lib/libArthasJniLibrary-x64.dll | Bin 0 -> 86115 bytes lib/libArthasJniLibrary-x64.dylib | Bin 0 -> 52392 bytes lib/libArthasJniLibrary-x64.so | Bin 0 -> 22360 bytes packaging/src/main/assembly/assembly.xml | 3 + pom.xml | 2 +- spy/pom.xml | 10 + spy/src/main/java/arthas/VmTool.java | 109 ++++++++ spy/src/main/java/arthas/VmToolMXBean.java | 48 ++++ spy/src/main/java/arthas/package-info.java | 8 + 16 files changed, 482 insertions(+), 27 deletions(-) create mode 100644 arthas-vmtool/src/main/java/arthas/package-info.java create mode 100644 common/src/main/java/com/taobao/arthas/common/VmToolUtils.java create mode 100644 core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java create mode 100644 lib/libArthasJniLibrary-x64.dll create mode 100644 lib/libArthasJniLibrary-x64.dylib create mode 100644 lib/libArthasJniLibrary-x64.so create mode 100644 spy/src/main/java/arthas/VmTool.java create mode 100644 spy/src/main/java/arthas/VmToolMXBean.java create mode 100644 spy/src/main/java/arthas/package-info.java diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index ad15d1271..6f7cc0a2a 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -2,8 +2,6 @@ package arthas; import java.util.ArrayList; -import com.taobao.arthas.common.OSUtils; - /** * @author ZhangZiCheng 2021-02-12 * @author hengyunabc 2021-04-26 @@ -16,24 +14,6 @@ public class VmTool implements VmToolMXBean { */ public final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; - private static String libName = null; - static { - if (OSUtils.isMac()) { - libName = "libArthasJniLibrary-x64.dylib"; - } - if (OSUtils.isLinux()) { - libName = "libArthasJniLibrary-x64.so"; - if (OSUtils.isArm32()) { - libName = "libArthasJniLibrary-arm.so"; - } else if (OSUtils.isArm64()) { - libName = "libArthasJniLibrary-aarch64.so"; - } - } - if (OSUtils.isWindows()) { - libName = "libArthasJniLibrary-x64.dll"; - } - } - private static VmTool instance; private VmTool() { @@ -58,10 +38,6 @@ public class VmTool implements VmToolMXBean { return instance; } - public static String detectLibName() { - return libName; - } - /** * 检测jni-lib是否正常,如果正常,应该输出OK */ diff --git a/arthas-vmtool/src/main/java/arthas/package-info.java b/arthas-vmtool/src/main/java/arthas/package-info.java new file mode 100644 index 000000000..ba203103d --- /dev/null +++ b/arthas-vmtool/src/main/java/arthas/package-info.java @@ -0,0 +1,6 @@ +/** + *
+ * 修改后要同步到 spy/src/main/java 。
+ * 
+ */ +package arthas; diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 223a853b5..381a3eaef 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -2,6 +2,8 @@ package arthas; import org.junit.Test; +import com.taobao.arthas.common.VmToolUtils; + import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -25,7 +27,7 @@ public class VmToolTest { String path = VmTool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); System.err.println(path); - String libPath = new File(path, VmTool.detectLibName()).getAbsolutePath(); + String libPath = new File(path, VmToolUtils.detectLibName()).getAbsolutePath(); VmTool vmtool = VmTool.getInstance(libPath); //调用native方法,获取已加载的类,不包括小类型(如int) diff --git a/common/src/main/java/com/taobao/arthas/common/VmToolUtils.java b/common/src/main/java/com/taobao/arthas/common/VmToolUtils.java new file mode 100644 index 000000000..7967b415e --- /dev/null +++ b/common/src/main/java/com/taobao/arthas/common/VmToolUtils.java @@ -0,0 +1,30 @@ +package com.taobao.arthas.common; + +/** + * + * @author hengyunabc 2021-04-27 + * + */ +public class VmToolUtils { + private static String libName = null; + static { + if (OSUtils.isMac()) { + libName = "libArthasJniLibrary-x64.dylib"; + } + if (OSUtils.isLinux()) { + libName = "libArthasJniLibrary-x64.so"; + if (OSUtils.isArm32()) { + libName = "libArthasJniLibrary-arm.so"; + } else if (OSUtils.isArm64()) { + libName = "libArthasJniLibrary-aarch64.so"; + } + } + if (OSUtils.isWindows()) { + libName = "libArthasJniLibrary-x64.dll"; + } + } + + public static String detectLibName() { + return libName; + } +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/BuiltinCommandPack.java b/core/src/main/java/com/taobao/arthas/core/command/BuiltinCommandPack.java index 1e9f91953..0bdcd36eb 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/BuiltinCommandPack.java +++ b/core/src/main/java/com/taobao/arthas/core/command/BuiltinCommandPack.java @@ -44,6 +44,7 @@ import com.taobao.arthas.core.command.monitor200.StackCommand; import com.taobao.arthas.core.command.monitor200.ThreadCommand; import com.taobao.arthas.core.command.monitor200.TimeTunnelCommand; import com.taobao.arthas.core.command.monitor200.TraceCommand; +import com.taobao.arthas.core.command.monitor200.VmToolCommand; import com.taobao.arthas.core.command.monitor200.WatchCommand; import com.taobao.arthas.core.shell.command.Command; import com.taobao.arthas.core.shell.command.CommandResolver; @@ -113,6 +114,7 @@ public class BuiltinCommandPack implements CommandResolver { commands.add(Command.create(GrepCommand.class)); commands.add(Command.create(TeeCommand.class)); commands.add(Command.create(ProfilerCommand.class)); + commands.add(Command.create(VmToolCommand.class)); commands.add(Command.create(ShutdownCommand.class)); commands.add(Command.create(StopCommand.class)); } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java new file mode 100644 index 000000000..744bf2c04 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -0,0 +1,261 @@ +package com.taobao.arthas.core.command.monitor200; + +import java.io.File; +import java.lang.instrument.Instrumentation; +import java.security.CodeSource; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.alibaba.arthas.deps.org.slf4j.Logger; +import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; +import com.taobao.arthas.common.VmToolUtils; +import com.taobao.arthas.core.command.Constants; +import com.taobao.arthas.core.command.express.Express; +import com.taobao.arthas.core.command.express.ExpressException; +import com.taobao.arthas.core.command.express.ExpressFactory; +import com.taobao.arthas.core.command.model.ClassLoaderVO; +import com.taobao.arthas.core.command.model.SearchClassModel; +import com.taobao.arthas.core.shell.cli.Completion; +import com.taobao.arthas.core.shell.cli.CompletionUtils; +import com.taobao.arthas.core.shell.cli.OptionCompleteHandler; +import com.taobao.arthas.core.shell.command.AnnotatedCommand; +import com.taobao.arthas.core.shell.command.CommandProcess; +import com.taobao.arthas.core.util.ClassLoaderUtils; +import com.taobao.arthas.core.util.ClassUtils; +import com.taobao.arthas.core.util.SearchUtils; +import com.taobao.arthas.core.view.ObjectView; +import com.taobao.middleware.cli.annotations.DefaultValue; +import com.taobao.middleware.cli.annotations.Description; +import com.taobao.middleware.cli.annotations.Name; +import com.taobao.middleware.cli.annotations.Option; +import com.taobao.middleware.cli.annotations.Summary; + +import arthas.VmTool; + +/** + * + * @author hengyunabc 2021-04-27 + * + */ +//@formatter:off +@Name("vmtool") +@Summary("jvm tool") +@Description(Constants.EXAMPLE + + " vmtool --action getInstances --className demo.MathGame\n" + + " vmtool --action getInstances --className demo.MathGame --express 'instances.size()'\n" + + Constants.WIKI + Constants.WIKI_HOME + "vmtool") +//@formatter:on +public class VmToolCommand extends AnnotatedCommand { + private static final Logger logger = LoggerFactory.getLogger(VmToolCommand.class); + + private VmToolAction action; + private String className; + private String express; + + private String hashCode = null; + private String classLoaderClass; + /** + * default value 2 + */ + private int expand; + + private static String libPath; + private static VmTool vmTool = null; + + static { + String libName = VmToolUtils.detectLibName(); + if (libName != null) { + CodeSource codeSource = VmToolCommand.class.getProtectionDomain().getCodeSource(); + if (codeSource != null) { + try { + File bootJarPath = new File(codeSource.getLocation().toURI().getSchemeSpecificPart()); + File soFile = new File(bootJarPath.getParentFile(), "lib" + File.separator + libName); + if (soFile.exists()) { + libPath = soFile.getAbsolutePath(); + } + } catch (Throwable e) { + logger.error("can not find VmTool so", e); + } + } + } + + } + + @Option(shortName = "a", longName = "action", required = true) + @Description("Action to execute") + public void setAction(VmToolAction action) { + this.action = action; + } + + @Option(longName = "className") + @Description("The class name") + public void setClassName(String className) { + this.className = className; + } + + @Option(shortName = "x", longName = "expand") + @Description("Expand level of object (2 by default)") + @DefaultValue("2") + public void setExpand(int expand) { + this.expand = expand; + } + + @Option(shortName = "c", longName = "classloader") + @Description("The hash code of the special class's classLoader") + public void setHashCode(String hashCode) { + this.hashCode = hashCode; + } + + @Option(longName = "classLoaderClass") + @Description("The class name of the special class's classLoader.") + public void setClassLoaderClass(String classLoaderClass) { + this.classLoaderClass = classLoaderClass; + } + + @Option(longName = "express", required = false) + @Description("The ognl expression, default valueis `instances`.") + public void setExpress(String express) { + this.express = express; + } + + public enum VmToolAction { + getInstances, load + } + + @Override + public void process(final CommandProcess process) { + try { + Instrumentation inst = process.session().getInstrumentation(); + + if (VmToolAction.getInstances.equals(action)) { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + if (hashCode == null && classLoaderClass != null) { + List matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, + classLoaderClass); + if (matchedClassLoaders.size() == 1) { + classLoader = matchedClassLoaders.get(0); + hashCode = Integer.toHexString(matchedClassLoaders.get(0).hashCode()); + } else if (matchedClassLoaders.size() > 1) { + Collection classLoaderVOList = ClassUtils + .createClassLoaderVOList(matchedClassLoaders); + SearchClassModel searchclassModel = new SearchClassModel().setClassLoaderClass(classLoaderClass) + .setMatchedClassLoaders(classLoaderVOList); + process.appendResult(searchclassModel); + process.end(-1, + "Found more than one classloader by class name, please specify classloader with '-c '"); + return; + } else { + process.end(-1, "Can not find classloader by class name: " + classLoaderClass + "."); + return; + } + } + + List> matchedClasses = new ArrayList>( + SearchUtils.searchClass(inst, className, false, hashCode)); + int matchedClassSize = matchedClasses.size(); + if (matchedClassSize == 0) { + process.end(-1, "Can not find class by class name: " + className + "."); + return; + } else if (matchedClassSize > 1) { + process.end(-1, "Found more than one class: " + matchedClasses + "."); + return; + } else { + ArrayList instances = vmToolInstance().getInstances(matchedClasses.get(0)); + Object value = instances; + if (express != null) { + Express unpooledExpress = ExpressFactory.unpooledExpress(classLoader); + try { + value = unpooledExpress.bind(new InstancesWrapper(instances)).get(express); + } catch (ExpressException e) { + logger.warn("ognl: failed execute express: " + express, e); + process.end(-1, "Failed to execute ognl, exception message: " + e.getMessage() + + ", please check $HOME/logs/arthas/arthas.log for more details. "); + } + } + + process.write(new ObjectView(value, this.expand).draw()); + process.end(); + } + } + + process.end(); + } catch (Throwable e) { + logger.error("vmtool error", e); + process.end(1, "vmtool error: " + e.getMessage()); + } + } + + static class InstancesWrapper { + Object instances; + + public InstancesWrapper(Object instances) { + this.instances = instances; + } + + public Object getInstances() { + return instances; + } + + public void setInstances(Object instances) { + this.instances = instances; + } + } + + private VmTool vmToolInstance() { + if (vmTool != null) { + return vmTool; + } else { + vmTool = VmTool.getInstance(libPath); + } + return vmTool; + } + + private Set actions() { + Set values = new HashSet(); + for (VmToolAction action : VmToolAction.values()) { + values.add(action.toString()); + } + return values; + } + + @Override + public void complete(Completion completion) { + List handlers = new ArrayList(); + + handlers.add(new OptionCompleteHandler() { + + @Override + public boolean matchName(String token) { + return "-a".equals(token) || "--action".equals(token); + } + + @Override + public boolean complete(Completion completion) { + return CompletionUtils.complete(completion, actions()); + } + + }); + + handlers.add(new OptionCompleteHandler() { + @Override + public boolean matchName(String token) { + return "--className".equals(token); + } + + @Override + public boolean complete(Completion completion) { + return CompletionUtils.completeClassName(completion); + } + }); + + if (CompletionUtils.completeOptions(completion, handlers)) { + return; + } + + super.complete(completion); + } + +} \ No newline at end of file diff --git a/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java b/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java index 0d6ca77ae..800f15960 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java @@ -181,7 +181,7 @@ public class ClassUtils { return list.toArray(new String[0]); } - public static List createClassVOList(Set> matchedClasses) { + public static List createClassVOList(Collection> matchedClasses) { List classVOs = new ArrayList(matchedClasses.size()); for (Class aClass : matchedClasses) { ClassVO classVO = createSimpleClassInfo(aClass); diff --git a/lib/libArthasJniLibrary-x64.dll b/lib/libArthasJniLibrary-x64.dll new file mode 100644 index 0000000000000000000000000000000000000000..b9c983aeecd74c8dc313ec75569bb70e50ff47f3 GIT binary patch literal 86115 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 literal 0 HcmV?d00001 diff --git a/lib/libArthasJniLibrary-x64.so b/lib/libArthasJniLibrary-x64.so new file mode 100644 index 0000000000000000000000000000000000000000..b24706f3b19cbf56b365a48c09bd3ddf03e8a1e1 GIT binary patch literal 22360 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 Ja4EP@@!yJ;IS~K= literal 0 HcmV?d00001 diff --git a/packaging/src/main/assembly/assembly.xml b/packaging/src/main/assembly/assembly.xml index f3e8ad630..121523e78 100644 --- a/packaging/src/main/assembly/assembly.xml +++ b/packaging/src/main/assembly/assembly.xml @@ -63,5 +63,8 @@ ../async-profiler + + ../lib + diff --git a/pom.xml b/pom.xml index 81ab30d75..207b72484 100644 --- a/pom.xml +++ b/pom.xml @@ -57,8 +57,8 @@ math-game - spy common + spy arthas-vmtool tunnel-common tunnel-client diff --git a/spy/pom.xml b/spy/pom.xml index 39722bc4d..b0ff9b411 100644 --- a/spy/pom.xml +++ b/spy/pom.xml @@ -10,6 +10,16 @@ arthas-spy arthas-spy + + + com.taobao.arthas + arthas-common + ${project.version} + provided + true + + + arthas-spy diff --git a/spy/src/main/java/arthas/VmTool.java b/spy/src/main/java/arthas/VmTool.java new file mode 100644 index 000000000..6f7cc0a2a --- /dev/null +++ b/spy/src/main/java/arthas/VmTool.java @@ -0,0 +1,109 @@ +package arthas; + +import java.util.ArrayList; + +/** + * @author ZhangZiCheng 2021-02-12 + * @author hengyunabc 2021-04-26 + * @since 3.5.1 + */ +public class VmTool implements VmToolMXBean { + + /** + * 不要修改jni-lib的名称 + */ + public final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; + + private static VmTool instance; + + private VmTool() { + } + + public static VmTool getInstance() { + return getInstance(null); + } + + public static synchronized VmTool getInstance(String libPath) { + if (instance != null) { + return instance; + } + + if (libPath == null) { + System.loadLibrary(JNI_LIBRARY_NAME); + } else { + System.load(libPath); + } + + instance = new VmTool(); + return instance; + } + + /** + * 检测jni-lib是否正常,如果正常,应该输出OK + */ + private static native String check0(); + + /** + * 获取某个class在jvm中当前所有存活实例 + */ + private static native ArrayList getInstances0(Class klass); + + /** + * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte + */ + private static native long sumInstanceSize0(Class klass); + + /** + * 获取某个实例的占用内存,单位:Byte + */ + private static native long getInstanceSize0(Object instance); + + /** + * 统计某个class在jvm中当前所有存活实例的总个数 + */ + private static native long countInstances0(Class klass); + + /** + * 获取所有已加载的类 + */ + private static native ArrayList> getAllLoadedClasses0(); + + /** + * 包括小类型(如int) + */ + @SuppressWarnings("all") + public static ArrayList getAllClasses() { + return getInstances0(Class.class); + } + + @Override + public String check() { + return check0(); + } + + @Override + public ArrayList getInstances(Class klass) { + return getInstances0(klass); + } + + @Override + public long sumInstanceSize(Class klass) { + return sumInstanceSize0(klass); + } + + @Override + public long getInstanceSize(Object instance) { + return getInstanceSize0(instance); + } + + @Override + public long countInstances(Class klass) { + return countInstances0(klass); + } + + @Override + public ArrayList> getAllLoadedClasses() { + return getAllLoadedClasses0(); + } + +} diff --git a/spy/src/main/java/arthas/VmToolMXBean.java b/spy/src/main/java/arthas/VmToolMXBean.java new file mode 100644 index 000000000..e70a17e7a --- /dev/null +++ b/spy/src/main/java/arthas/VmToolMXBean.java @@ -0,0 +1,48 @@ +package arthas; + +import java.util.ArrayList; + +/** + * VmTool interface for JMX server. How to register VmTool MBean: + * + *
+ * {@code
+ *     ManagementFactory.getPlatformMBeanServer().registerMBean(
+ *             VmTool.getInstance(),
+ *             new ObjectName("arthas:type=VmTool")
+ *     );
+ * }
+ * 
+ * @author hengyunabc 2021-04-26 + */ +public interface VmToolMXBean { + /** + * 检测jni-lib是否正常,如果正常,应该输出OK + */ + public String check(); + + /** + * 获取某个class在jvm中当前所有存活实例 + */ + public ArrayList getInstances(Class klass); + + /** + * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte + */ + public long sumInstanceSize(Class klass); + + /** + * 获取某个实例的占用内存,单位:Byte + */ + public long getInstanceSize(Object instance); + + /** + * 统计某个class在jvm中当前所有存活实例的总个数 + */ + public long countInstances(Class klass); + + /** + * 获取所有已加载的类 + */ + public ArrayList> getAllLoadedClasses(); +} diff --git a/spy/src/main/java/arthas/package-info.java b/spy/src/main/java/arthas/package-info.java new file mode 100644 index 000000000..8762944ed --- /dev/null +++ b/spy/src/main/java/arthas/package-info.java @@ -0,0 +1,8 @@ +/** + *
+ * copy from arthas-vmtool/src/main/java 。
+ * 因为动态链接库只能被加载一次,只能使用一份代码。放在spy jar里保证只有一份。
+ * TODO 当arthas本身版本升级时,已append 到bootstrap classloader的spy jar不能升级,VmTool的接口可以会调用失败。
+ * 
+ */ +package arthas; From 6623ef44c6017d5bc52a316ac9d731a37254ed82 Mon Sep 17 00:00:00 2001 From: dragon-zhang <38336731+dragon-zhang@users.noreply.github.com> Date: Fri, 30 Apr 2021 16:31:44 +0800 Subject: [PATCH 14/31] return array in VmTool native method, fix jni memory leak problem #1781 --- .../src/main/java/arthas/VmTool.java | 13 +- .../src/main/java/arthas/VmToolMXBean.java | 6 +- .../src/main/native/include/arthas_VmTool.h | 26 ++-- .../src/main/native/src/jni-library.cpp | 44 ++++--- .../src/test/java/arthas/VmToolTest.java | 114 ++++++++++++++++-- .../command/monitor200/VmToolCommand.java | 3 +- pom.xml | 5 - spy/src/main/java/arthas/VmTool.java | 13 +- spy/src/main/java/arthas/VmToolMXBean.java | 6 +- 9 files changed, 159 insertions(+), 71 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index 6f7cc0a2a..ae08763d7 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -1,7 +1,5 @@ package arthas; -import java.util.ArrayList; - /** * @author ZhangZiCheng 2021-02-12 * @author hengyunabc 2021-04-26 @@ -46,7 +44,7 @@ public class VmTool implements VmToolMXBean { /** * 获取某个class在jvm中当前所有存活实例 */ - private static native ArrayList getInstances0(Class klass); + private static native T[] getInstances0(Class klass); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte @@ -66,13 +64,12 @@ public class VmTool implements VmToolMXBean { /** * 获取所有已加载的类 */ - private static native ArrayList> getAllLoadedClasses0(); + private static native Class[] getAllLoadedClasses0(); /** * 包括小类型(如int) */ - @SuppressWarnings("all") - public static ArrayList getAllClasses() { + public static Class[] getAllClasses() { return getInstances0(Class.class); } @@ -82,7 +79,7 @@ public class VmTool implements VmToolMXBean { } @Override - public ArrayList getInstances(Class klass) { + public T[] getInstances(Class klass) { return getInstances0(klass); } @@ -102,7 +99,7 @@ public class VmTool implements VmToolMXBean { } @Override - public ArrayList> getAllLoadedClasses() { + public Class[] getAllLoadedClasses() { return getAllLoadedClasses0(); } diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index e70a17e7a..51af311ae 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -1,7 +1,5 @@ package arthas; -import java.util.ArrayList; - /** * VmTool interface for JMX server. How to register VmTool MBean: * @@ -24,7 +22,7 @@ public interface VmToolMXBean { /** * 获取某个class在jvm中当前所有存活实例 */ - public ArrayList getInstances(Class klass); + public T[] getInstances(Class klass); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte @@ -44,5 +42,5 @@ public interface VmToolMXBean { /** * 获取所有已加载的类 */ - public ArrayList> getAllLoadedClasses(); + public Class[] getAllLoadedClasses(); } diff --git a/arthas-vmtool/src/main/native/include/arthas_VmTool.h b/arthas-vmtool/src/main/native/include/arthas_VmTool.h index 87098bfac..3f11b40a6 100644 --- a/arthas-vmtool/src/main/native/include/arthas_VmTool.h +++ b/arthas-vmtool/src/main/native/include/arthas_VmTool.h @@ -9,7 +9,7 @@ extern "C" { #endif /* * Class: arthas_VmTool - * Method: check + * Method: check0 * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0 @@ -17,42 +17,42 @@ JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0 /* * Class: arthas_VmTool - * Method: getInstances - * Signature: (Ljava/lang/Class;)Ljava/util/ArrayList; + * Method: getInstances0 + * Signature: (Ljava/lang/Class;)[Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_arthas_VmTool_getInstances +JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getInstances0 (JNIEnv *, jclass, jclass); /* * Class: arthas_VmTool - * Method: sumInstanceSize + * Method: sumInstanceSize0 * Signature: (Ljava/lang/Class;)J */ -JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize +JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize0 (JNIEnv *, jclass, jclass); /* * Class: arthas_VmTool - * Method: getInstanceSize + * Method: getInstanceSize0 * Signature: (Ljava/lang/Object;)J */ -JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize +JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 (JNIEnv *, jclass, jobject); /* * Class: arthas_VmTool - * Method: countInstances + * Method: countInstances0 * Signature: (Ljava/lang/Class;)J */ -JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances +JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances0 (JNIEnv *, jclass, jclass); /* * Class: arthas_VmTool - * Method: getAllLoadedClasses - * Signature: ()Ljava/util/ArrayList; + * Method: getAllLoadedClasses0 + * Signature: ()[Ljava/lang/Class; */ -JNIEXPORT jobject JNICALL Java_arthas_VmTool_getAllLoadedClasses +JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 (JNIEnv *, jclass); #ifdef __cplusplus diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 776124cdf..95fab8f62 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -4,6 +4,21 @@ #include #include "arthas_VmTool.h" +//缓存 +static jclass cachedClass = NULL; + +extern "C" +JNIEXPORT jclass JNICALL getClass(JNIEnv *env) { + if (cachedClass == NULL) { + //通过其签名找到Class的Class + jclass theClass = env->FindClass("java/lang/Class"); + //放入缓存 + cachedClass = static_cast(env->NewGlobalRef(theClass)); + env->DeleteLocalRef(theClass); + } + return cachedClass; +} + extern "C" JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { @@ -46,7 +61,7 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) } extern "C" -JNIEXPORT jobject JNICALL +JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -75,15 +90,13 @@ Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { return JNI_FALSE; } - //通过其签名找到ArrayList的Class - jclass arrayListClass = env->FindClass("java/util/ArrayList"); - jobject arrayList = createJavaInstance(env, arrayListClass); - jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); - //添加元素到ArrayList实例 + jobjectArray array = env->NewObjectArray(count, klass, NULL); + //添加元素到数组 for (int i = 0; i < count; i++) { - env->CallObjectMethod(arrayList, addMethod, instances[i]); + env->SetObjectArrayElement(array, i, instances[i]); } - return arrayList; + jvmti->Deallocate(reinterpret_cast(instances)); + return array; } extern "C" @@ -122,6 +135,7 @@ Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) jvmti->GetObjectSize(instances[i], &size); sum = sum + size; } + jvmti->Deallocate(reinterpret_cast(instances)); return sum; } @@ -172,7 +186,7 @@ Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) } extern "C" -JNIEXPORT jobject JNICALL Java_arthas_VmTool_getAllLoadedClasses0 +JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 (JNIEnv *env, jclass thisClass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -186,13 +200,11 @@ JNIEXPORT jobject JNICALL Java_arthas_VmTool_getAllLoadedClasses0 return JNI_FALSE; } - //通过其签名找到ArrayList的Class - jclass arrayListClass = env->FindClass("java/util/ArrayList"); - jobject arrayList = createJavaInstance(env, arrayListClass); - jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); - //添加元素到ArrayList实例 + jobjectArray array = env->NewObjectArray(count, getClass(env), NULL); + //添加元素到数组 for (int i = 0; i < count; i++) { - env->CallObjectMethod(arrayList, addMethod, classes[i]); + env->SetObjectArrayElement(array, i, classes[i]); } - return arrayList; + jvmti->Deallocate(reinterpret_cast(classes)); + return array; } \ No newline at end of file diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 381a3eaef..03d3e11a4 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -6,8 +6,11 @@ import com.taobao.arthas.common.VmToolUtils; import java.io.File; import java.lang.ref.WeakReference; -import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicLong; +/** + * 以下本地测试的jvm参数均为:-Xms128m -Xmx128m + */ public class VmToolTest { /** @@ -22,23 +25,18 @@ public class VmToolTest { * after instances->[] */ @Test - public void test01() { + public void testIsSnapshot() { try { - String path = VmTool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - System.err.println(path); - - String libPath = new File(path, VmToolUtils.detectLibName()).getAbsolutePath(); - VmTool vmtool = VmTool.getInstance(libPath); - + VmTool vmtool = initVmTool(); //调用native方法,获取已加载的类,不包括小类型(如int) - ArrayList> allLoadedClasses = vmtool.getAllLoadedClasses(); - System.out.println("allLoadedClasses->" + allLoadedClasses.size()); + Class[] allLoadedClasses = vmtool.getAllLoadedClasses(); + System.out.println("allLoadedClasses->" + allLoadedClasses.length); //通过下面的例子,可以看到getInstances(Class klass)拿到的是当前存活的所有对象 WeakReference weakReference1 = new WeakReference(new VmToolTest()); WeakReference weakReference2 = new WeakReference(new VmToolTest()); System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList beforeInstances = vmtool.getInstances(VmTool.class); + VmTool[] beforeInstances = vmtool.getInstances(VmTool.class); System.out.println("before instances->" + beforeInstances); System.out.println("size->" + vmtool.getInstanceSize(weakReference1.get())); System.out.println("count->" + vmtool.countInstances(VmTool.class)); @@ -48,10 +46,102 @@ public class VmToolTest { System.gc(); Thread.sleep(100); System.out.println(weakReference1.get() + " " + weakReference2.get()); - ArrayList afterInstances = vmtool.getInstances(VmTool.class); + VmTool[] afterInstances = vmtool.getInstances(VmTool.class); System.out.println("after instances->" + afterInstances); } catch (Exception e) { e.printStackTrace(); } } + + private VmTool initVmTool() { + String path = VmTool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + System.err.println(path); + + String libPath = new File(path, VmToolUtils.detectLibName()).getAbsolutePath(); + return VmTool.getInstance(libPath); + } + + @Test + public void testGetInstancesMemoryLeak() { + //这里睡20s是为了方便用jprofiler连接上进程 +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + VmTool vmtool = initVmTool(); + final AtomicLong totalTime = new AtomicLong(); + //本地测试请改成200000 + for (int i = 1; i <= 2; i++) { + long start = System.currentTimeMillis(); + WeakReference reference = new WeakReference(vmtool.getInstances(Object.class)); + Object[] instances = reference.get(); + long cost = System.currentTimeMillis() - start; + totalTime.addAndGet(cost); + System.out.println(i + " instance size:" + (instances == null ? 0 : instances.length) + ", cost " + cost + "ms avgCost " + totalTime.doubleValue() / i + "ms"); + instances = null; + System.gc(); + } + } + + @Test + public void testSumInstancesMemoryLeak() { + //这里睡20s是为了方便用jprofiler连接上进程 +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + VmTool vmtool = initVmTool(); + final AtomicLong totalTime = new AtomicLong(); + //本地测试请改成200000 + for (int i = 1; i <= 2; i++) { + long start = System.currentTimeMillis(); + long sum = vmtool.sumInstanceSize(Object.class); + long cost = System.currentTimeMillis() - start; + totalTime.addAndGet(cost); + System.out.println(i + " sum:" + sum + ", cost " + cost + "ms avgCost " + totalTime.doubleValue() / i + "ms"); + } + } + + @Test + public void testCountInstancesMemoryLeak() { + //这里睡20s是为了方便用jprofiler连接上进程 +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + VmTool vmtool = initVmTool(); + final AtomicLong totalTime = new AtomicLong(); + //本地测试请改成200000 + for (int i = 1; i <= 2; i++) { + long start = System.currentTimeMillis(); + long count = vmtool.countInstances(Object.class); + long cost = System.currentTimeMillis() - start; + totalTime.addAndGet(cost); + System.out.println(i + " count:" + count + ", cost " + cost + "ms avgCost " + totalTime.doubleValue() / i + "ms"); + } + } + + @Test + public void testGetAllLoadedClassesMemoryLeak() { + //这里睡20s是为了方便用jprofiler连接上进程 +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + VmTool vmtool = initVmTool(); + final AtomicLong totalTime = new AtomicLong(); + //本地测试请改成200000 + for (int i = 1; i <= 2; i++) { + long start = System.currentTimeMillis(); + Class[] allLoadedClasses = vmtool.getAllLoadedClasses(); + long cost = System.currentTimeMillis() - start; + totalTime.addAndGet(cost); + System.out.println(i + " class size:" + allLoadedClasses.length + ", cost " + cost + "ms avgCost " + totalTime.doubleValue() / i + "ms"); + allLoadedClasses = null; + } + } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 744bf2c04..bd17d6e16 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -38,6 +38,7 @@ import arthas.VmTool; /** * * @author hengyunabc 2021-04-27 + * @author ZhangZiCheng 2021-04-29 * */ //@formatter:off @@ -163,7 +164,7 @@ public class VmToolCommand extends AnnotatedCommand { process.end(-1, "Found more than one class: " + matchedClasses + "."); return; } else { - ArrayList instances = vmToolInstance().getInstances(matchedClasses.get(0)); + Object[] instances = vmToolInstance().getInstances(matchedClasses.get(0)); Object value = instances; if (express != null) { Express unpooledExpress = ExpressFactory.unpooledExpress(classLoader); diff --git a/pom.xml b/pom.xml index 207b72484..9dd037c17 100644 --- a/pom.xml +++ b/pom.xml @@ -217,11 +217,6 @@ zt-zip 1.14 - - org.scijava - native-lib-loader - 2.0.2 - diff --git a/spy/src/main/java/arthas/VmTool.java b/spy/src/main/java/arthas/VmTool.java index 6f7cc0a2a..ae08763d7 100644 --- a/spy/src/main/java/arthas/VmTool.java +++ b/spy/src/main/java/arthas/VmTool.java @@ -1,7 +1,5 @@ package arthas; -import java.util.ArrayList; - /** * @author ZhangZiCheng 2021-02-12 * @author hengyunabc 2021-04-26 @@ -46,7 +44,7 @@ public class VmTool implements VmToolMXBean { /** * 获取某个class在jvm中当前所有存活实例 */ - private static native ArrayList getInstances0(Class klass); + private static native T[] getInstances0(Class klass); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte @@ -66,13 +64,12 @@ public class VmTool implements VmToolMXBean { /** * 获取所有已加载的类 */ - private static native ArrayList> getAllLoadedClasses0(); + private static native Class[] getAllLoadedClasses0(); /** * 包括小类型(如int) */ - @SuppressWarnings("all") - public static ArrayList getAllClasses() { + public static Class[] getAllClasses() { return getInstances0(Class.class); } @@ -82,7 +79,7 @@ public class VmTool implements VmToolMXBean { } @Override - public ArrayList getInstances(Class klass) { + public T[] getInstances(Class klass) { return getInstances0(klass); } @@ -102,7 +99,7 @@ public class VmTool implements VmToolMXBean { } @Override - public ArrayList> getAllLoadedClasses() { + public Class[] getAllLoadedClasses() { return getAllLoadedClasses0(); } diff --git a/spy/src/main/java/arthas/VmToolMXBean.java b/spy/src/main/java/arthas/VmToolMXBean.java index e70a17e7a..51af311ae 100644 --- a/spy/src/main/java/arthas/VmToolMXBean.java +++ b/spy/src/main/java/arthas/VmToolMXBean.java @@ -1,7 +1,5 @@ package arthas; -import java.util.ArrayList; - /** * VmTool interface for JMX server. How to register VmTool MBean: * @@ -24,7 +22,7 @@ public interface VmToolMXBean { /** * 获取某个class在jvm中当前所有存活实例 */ - public ArrayList getInstances(Class klass); + public T[] getInstances(Class klass); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte @@ -44,5 +42,5 @@ public interface VmToolMXBean { /** * 获取所有已加载的类 */ - public ArrayList> getAllLoadedClasses(); + public Class[] getAllLoadedClasses(); } From ac27ea39223ccd95602546a00c56e0bfc88b2626 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 30 Apr 2021 16:36:44 +0800 Subject: [PATCH 15/31] improve arthas-vmtool package jar config --- arthas-vmtool/pom.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index 6f5cc74f7..78d98b111 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -64,7 +64,6 @@ - arthas-vmtool org.apache.maven.plugins @@ -81,19 +80,6 @@ org.apache.maven.plugins maven-jar-plugin 2.4 - - - default-jar - package - - jar - - - ${os_name}-${os.arch} - ${project.build.directory}/classes - - - org.codehaus.mojo From 3499a307e2d8258dc170a41e5e5638d067e54214 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 30 Apr 2021 17:40:08 +0800 Subject: [PATCH 16/31] vmtool command support forceGc action. #1781 --- .../src/main/java/arthas/VmTool.java | 7 +++++++ .../src/main/java/arthas/VmToolMXBean.java | 5 +++++ .../src/main/native/include/arthas_VmTool.h | 8 ++++++++ .../src/main/native/src/jni-library.cpp | 19 ++++++++++++------ .../src/test/java/arthas/VmToolTest.java | 4 ++-- .../command/monitor200/VmToolCommand.java | 11 ++++++++-- lib/libArthasJniLibrary-x64.dylib | Bin 52392 -> 53248 bytes spy/src/main/java/arthas/VmTool.java | 7 +++++++ spy/src/main/java/arthas/VmToolMXBean.java | 5 +++++ 9 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index ae08763d7..d530a06d5 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -41,6 +41,8 @@ public class VmTool implements VmToolMXBean { */ private static native String check0(); + private static native void forceGc0(); + /** * 获取某个class在jvm中当前所有存活实例 */ @@ -78,6 +80,11 @@ public class VmTool implements VmToolMXBean { return check0(); } + @Override + public void forceGc() { + forceGc0(); + } + @Override public T[] getInstances(Class klass) { return getInstances0(klass); diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index 51af311ae..92df09be1 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -19,6 +19,11 @@ public interface VmToolMXBean { */ public String check(); + /** + * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection + */ + public void forceGc(); + /** * 获取某个class在jvm中当前所有存活实例 */ diff --git a/arthas-vmtool/src/main/native/include/arthas_VmTool.h b/arthas-vmtool/src/main/native/include/arthas_VmTool.h index 3f11b40a6..4f7b087f8 100644 --- a/arthas-vmtool/src/main/native/include/arthas_VmTool.h +++ b/arthas-vmtool/src/main/native/include/arthas_VmTool.h @@ -15,6 +15,14 @@ extern "C" { JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0 (JNIEnv *, jclass); +/* + * Class: arthas_VmTool + * Method: forceGc0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_arthas_VmTool_forceGc0 + (JNIEnv *, jclass); + /* * Class: arthas_VmTool * Method: getInstances0 diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 95fab8f62..0351dfead 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -19,12 +19,6 @@ JNIEXPORT jclass JNICALL getClass(JNIEnv *env) { return cachedClass; } -extern "C" -JNIEXPORT jstring JNICALL -Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { - return env->NewStringUTF("OK"); -} - extern "C" jvmtiEnv *getJvmtiEnv(JNIEnv *env) { @@ -36,6 +30,19 @@ jvmtiEnv *getJvmtiEnv(JNIEnv *env) { return jvmti; } +extern "C" +JNIEXPORT void JNICALL +Java_arthas_VmTool_forceGc0(JNIEnv *env, jclass thisClass) { + jvmtiEnv *jvmti = getJvmtiEnv(env); + jvmti->ForceGarbageCollection(); +} + +extern "C" +JNIEXPORT jstring JNICALL +Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { + return env->NewStringUTF("OK"); +} + extern "C" jobject createJavaInstance(JNIEnv *env, jclass javaClass) { //找到java类的构造方法 diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 03d3e11a4..16a7bac47 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -43,7 +43,7 @@ public class VmToolTest { System.out.println("sum size->" + vmtool.sumInstanceSize(VmTool.class)); beforeInstances = null; - System.gc(); + vmtool.forceGc(); Thread.sleep(100); System.out.println(weakReference1.get() + " " + weakReference2.get()); VmTool[] afterInstances = vmtool.getInstances(VmTool.class); @@ -80,7 +80,7 @@ public class VmToolTest { totalTime.addAndGet(cost); System.out.println(i + " instance size:" + (instances == null ? 0 : instances.length) + ", cost " + cost + "ms avgCost " + totalTime.doubleValue() / i + "ms"); instances = null; - System.gc(); + vmtool.forceGc(); } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index bd17d6e16..05ab8cd12 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -46,7 +46,8 @@ import arthas.VmTool; @Summary("jvm tool") @Description(Constants.EXAMPLE + " vmtool --action getInstances --className demo.MathGame\n" - + " vmtool --action getInstances --className demo.MathGame --express 'instances.size()'\n" + + " vmtool --action getInstances --className demo.MathGame --express 'instances.length'\n" + + " vmtool --action forceGc\n" + Constants.WIKI + Constants.WIKI_HOME + "vmtool") //@formatter:on public class VmToolCommand extends AnnotatedCommand { @@ -123,7 +124,7 @@ public class VmToolCommand extends AnnotatedCommand { } public enum VmToolAction { - getInstances, load + getInstances, forceGc, load } @Override @@ -178,8 +179,14 @@ public class VmToolCommand extends AnnotatedCommand { } process.write(new ObjectView(value, this.expand).draw()); + process.write("\n"); process.end(); } + } else if (VmToolAction.forceGc.equals(action)) { + vmToolInstance().forceGc(); + process.write("\n"); + process.end(); + return; } process.end(); diff --git a/lib/libArthasJniLibrary-x64.dylib b/lib/libArthasJniLibrary-x64.dylib index 8ab0de5863792556d53b295b19beafe6d9d12d73..5547993f54f3f17dad8737f111553030136e765f 100644 GIT binary patch literal 53248 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 delta 3310 zcmZ`*dr(x@8UOCRyDRcqKv60xG%YC>WiKEgZ_r%5;A^SUX>D{_mqoy3AMrdCN}>^kivmp;ZcnKty{(C^#_Ne#KP z=YHpV{mwbx9Oh zeFfhVkPp~Oh9zI+Ow4i8%w;p_q?;?qJnmEc6BGiJ=VX{H9nYRmCQZ8144230w7X2l zdR#|MR+qcO+DC{^AUAaD8_%!+u}c8?=s%CNgTrm$JPXIED*$VePD}vAQJ#czGYT`3b+5 zbej^^6d*4K20jvlyCu;-{Ti?g?-%|gDN#}k+La%vQ z9cYnI7e#Rdq~_G&)kVh`_I4@>6$jYnRI;w5AVEw9FebH!NQ}?s+mJzrb|lgyM&>gx z;UkfP`L7_*Z>eT*Ecf8$;m3+rFzg%2B(gcc6p^(h8`=Cs(p9?CbmFf*Jf`T!?fX6G z*Ak~kk<9;ISU}KOF`!?k;Ky*9m_+WBW_f?G9KbJ(4GxTf@#K1R4|vAJV9iw&*CoW~(lR-yOfWV%(7!*cd!_?BFtX)`GX!J*=;-#^lRj_j@_HqsU zeR85K&--4&lDj#sc+8-7aW_MBEjd%ACs8f+Q>9-Bt2+!!H~%H?@QfzFy!Fr}gDDPb zU#QrJ#s!K50b!_0*fC-ZZqjfA9&~L9i2>ofXxlv`29hT*B8ljRwu4c|FAU9%<4Mur z3@$v6bY46$=0kt-f~kOXmA_AJ7H%3oS(J$BT88=mE}O-WzZCOq(K5LV^7U#NL`v5% z{~!ewh2D$0B?FL*mbf_8E(Rd!^Xd5B{FkT0g88TE@GOlzi(g{7nhR$`Q>3TV#sJ% z@|MOvrC_h1*knuf7G{h*QoSm{s)$F)Q`OtOpZ;BjkBmID7 zAJuBap+ozY(mB0tl3|&A$Kw>D3@{-S;unUAV8g@{kS5A^{;=6_ceOWSqGkX-1f&m7 zzax~ED-<-U+NJS|oLBi!rNXC`DKxBp*uyGcuTk|Y-lS3$eRz){BOiCtv-;_%jxiE_ z)J=R-spOUDj-;|}R)<45Itjd$OFoRIlCEn;a_-F&ByD;vv0nN$VP~vmAqC6Tkx_54 zSo+*n+fj?H*{p6+mXYEv49@*uIxt#BmTo3vP$qO%MI;-GbR%uFNbj!;$mX9`OE=+urGHlO5${ zFHqP+!096Rg19`hARB6>tc@z#aOT5uXSI{V8C`?Jv8%`0W>=8x7>jo?Oh{hVDN&1I zXrk1q2!5(BE^l<(U6_l#Bx&Y5x?dUa4^Zy-H`reqNO=02?5hTveshM2~`-etzolQ5v)=L+MnGbjjvMlEh-+0=$JoUZ6r|;ml4xKdACrzc;JAS8MzqsRHc+_>IP^7rSwk`> f9pw4R3wRMVf8i23bnO|ezN>igJWhT*V`JcdMf8$1 diff --git a/spy/src/main/java/arthas/VmTool.java b/spy/src/main/java/arthas/VmTool.java index ae08763d7..d530a06d5 100644 --- a/spy/src/main/java/arthas/VmTool.java +++ b/spy/src/main/java/arthas/VmTool.java @@ -41,6 +41,8 @@ public class VmTool implements VmToolMXBean { */ private static native String check0(); + private static native void forceGc0(); + /** * 获取某个class在jvm中当前所有存活实例 */ @@ -78,6 +80,11 @@ public class VmTool implements VmToolMXBean { return check0(); } + @Override + public void forceGc() { + forceGc0(); + } + @Override public T[] getInstances(Class klass) { return getInstances0(klass); diff --git a/spy/src/main/java/arthas/VmToolMXBean.java b/spy/src/main/java/arthas/VmToolMXBean.java index 51af311ae..92df09be1 100644 --- a/spy/src/main/java/arthas/VmToolMXBean.java +++ b/spy/src/main/java/arthas/VmToolMXBean.java @@ -19,6 +19,11 @@ public interface VmToolMXBean { */ public String check(); + /** + * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection + */ + public void forceGc(); + /** * 获取某个class在jvm中当前所有存活实例 */ From 00430ca4228ccb24fccfcaf52b9f606f549345c9 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 30 Apr 2021 19:11:52 +0800 Subject: [PATCH 17/31] generate jni header file by maven javah goal. --- arthas-vmtool/pom.xml | 9 ++- .../src/main/native/include/arthas_VmTool.h | 69 ------------------- .../src/main/native/src/jni-library.cpp | 2 +- 3 files changed, 7 insertions(+), 73 deletions(-) delete mode 100644 arthas-vmtool/src/main/native/include/arthas_VmTool.h diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index 78d98b111..1e400d404 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -87,6 +87,11 @@ 1.0-alpha-11 true + + + arthas.VmTool + + ${project.basedir}/src/main/native/head ${os_name} @@ -96,9 +101,6 @@ jni-library.cpp - - src/main/native/include - generic-classic @@ -127,6 +129,7 @@ javah compile + javah initialize compile link diff --git a/arthas-vmtool/src/main/native/include/arthas_VmTool.h b/arthas-vmtool/src/main/native/include/arthas_VmTool.h deleted file mode 100644 index 4f7b087f8..000000000 --- a/arthas-vmtool/src/main/native/include/arthas_VmTool.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class arthas_VmTool */ - -#ifndef _Included_arthas_VmTool -#define _Included_arthas_VmTool -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: arthas_VmTool - * Method: check0 - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_arthas_VmTool_check0 - (JNIEnv *, jclass); - -/* - * Class: arthas_VmTool - * Method: forceGc0 - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_arthas_VmTool_forceGc0 - (JNIEnv *, jclass); - -/* - * Class: arthas_VmTool - * Method: getInstances0 - * Signature: (Ljava/lang/Class;)[Ljava/lang/Object; - */ -JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getInstances0 - (JNIEnv *, jclass, jclass); - -/* - * Class: arthas_VmTool - * Method: sumInstanceSize0 - * Signature: (Ljava/lang/Class;)J - */ -JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize0 - (JNIEnv *, jclass, jclass); - -/* - * Class: arthas_VmTool - * Method: getInstanceSize0 - * Signature: (Ljava/lang/Object;)J - */ -JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 - (JNIEnv *, jclass, jobject); - -/* - * Class: arthas_VmTool - * Method: countInstances0 - * Signature: (Ljava/lang/Class;)J - */ -JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances0 - (JNIEnv *, jclass, jclass); - -/* - * Class: arthas_VmTool - * Method: getAllLoadedClasses0 - * Signature: ()[Ljava/lang/Class; - */ -JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 0351dfead..7ffa8c9e3 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -2,7 +2,7 @@ #include #include #include -#include "arthas_VmTool.h" +#include "arthas_VmTool.h" // under target/native/javah/ //缓存 static jclass cachedClass = NULL; From 46273d268591d105ed19c60fe2d319a7d55ddd03 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 11:52:23 +0800 Subject: [PATCH 18/31] improve vmtool getAllLoadedClasses0 --- .../src/main/java/arthas/VmTool.java | 13 ++++--------- .../src/main/native/src/jni-library.cpp | 19 ++----------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index d530a06d5..aaed0dc20 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -65,15 +65,10 @@ public class VmTool implements VmToolMXBean { /** * 获取所有已加载的类 + * @param klass 这个参数必须是 Class.class + * @return */ - private static native Class[] getAllLoadedClasses0(); - - /** - * 包括小类型(如int) - */ - public static Class[] getAllClasses() { - return getInstances0(Class.class); - } + private static native Class[] getAllLoadedClasses0(Class klass); @Override public String check() { @@ -107,7 +102,7 @@ public class VmTool implements VmToolMXBean { @Override public Class[] getAllLoadedClasses() { - return getAllLoadedClasses0(); + return getAllLoadedClasses0(Class.class); } } diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 7ffa8c9e3..1f358d9d7 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -4,21 +4,6 @@ #include #include "arthas_VmTool.h" // under target/native/javah/ -//缓存 -static jclass cachedClass = NULL; - -extern "C" -JNIEXPORT jclass JNICALL getClass(JNIEnv *env) { - if (cachedClass == NULL) { - //通过其签名找到Class的Class - jclass theClass = env->FindClass("java/lang/Class"); - //放入缓存 - cachedClass = static_cast(env->NewGlobalRef(theClass)); - env->DeleteLocalRef(theClass); - } - return cachedClass; -} - extern "C" jvmtiEnv *getJvmtiEnv(JNIEnv *env) { @@ -194,7 +179,7 @@ Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) extern "C" JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 - (JNIEnv *env, jclass thisClass) { + (JNIEnv *env, jclass thisClass, jclass kclass) { jvmtiEnv *jvmti = getJvmtiEnv(env); @@ -207,7 +192,7 @@ JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 return JNI_FALSE; } - jobjectArray array = env->NewObjectArray(count, getClass(env), NULL); + jobjectArray array = env->NewObjectArray(count, kclass, NULL); //添加元素到数组 for (int i = 0; i < count; i++) { env->SetObjectArrayElement(array, i, classes[i]); From fe22e0f4fb2c6d2f68018b0e50be7f8d63f163ea Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 16:35:42 +0800 Subject: [PATCH 19/31] init jvmtiEnv through JNI_OnLoad method. --- .../src/main/native/src/jni-library.cpp | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 1f358d9d7..c1dfa0c92 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -4,21 +4,40 @@ #include #include "arthas_VmTool.h" // under target/native/javah/ + +static jvmtiEnv *jvmti; + extern "C" -jvmtiEnv *getJvmtiEnv(JNIEnv *env) { +int init_agent(JavaVM *vm, void *reserved) { + jint rc; + /* Get JVMTI environment */ + rc = vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_2); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: arthas vmtool Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc); + return -1; + } + return JNI_OK; +} - JavaVM *vm; - env->GetJavaVM(&vm); +extern "C" JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { + return init_agent(vm, reserved); +} - jvmtiEnv *jvmti; - vm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_2); - return jvmti; +extern "C" JNIEXPORT jint JNICALL +Agent_OnAttach(JavaVM* vm, char* options, void* reserved) { + return init_agent(vm, reserved); +} + +extern "C" JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM* vm, void* reserved) { + init_agent(vm, reserved); + return JNI_VERSION_1_6; } extern "C" JNIEXPORT void JNICALL Java_arthas_VmTool_forceGc0(JNIEnv *env, jclass thisClass) { - jvmtiEnv *jvmti = getJvmtiEnv(env); jvmti->ForceGarbageCollection(); } @@ -55,9 +74,6 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) extern "C" JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { - - jvmtiEnv *jvmti = getJvmtiEnv(env); - jvmtiCapabilities capabilities = {0}; capabilities.can_tag_objects = 1; jvmtiError error = jvmti->AddCapabilities(&capabilities); @@ -94,9 +110,6 @@ Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { - - jvmtiEnv *jvmti = getJvmtiEnv(env); - jvmtiCapabilities capabilities = {0}; capabilities.can_tag_objects = 1; jvmtiError error = jvmti->AddCapabilities(&capabilities); @@ -134,9 +147,6 @@ Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 (JNIEnv *env, jclass thisClass, jobject instance) { - - jvmtiEnv *jvmti = getJvmtiEnv(env); - jlong size = -1; jvmtiError error = jvmti->GetObjectSize(instance, &size); if (error) { @@ -149,9 +159,6 @@ JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { - - jvmtiEnv *jvmti = getJvmtiEnv(env); - jvmtiCapabilities capabilities = {0}; capabilities.can_tag_objects = 1; jvmtiError error = jvmti->AddCapabilities(&capabilities); @@ -180,9 +187,6 @@ Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) extern "C" JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 (JNIEnv *env, jclass thisClass, jclass kclass) { - - jvmtiEnv *jvmti = getJvmtiEnv(env); - jclass *classes; jint count = 0; From 35581b1cf41f5a242449a116fe3497176be05192 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 16:42:16 +0800 Subject: [PATCH 20/31] jvmti AddCapabilities when init --- .../src/main/native/src/jni-library.cpp | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index c1dfa0c92..a953dce29 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -16,6 +16,15 @@ int init_agent(JavaVM *vm, void *reserved) { fprintf(stderr, "ERROR: arthas vmtool Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc); return -1; } + + jvmtiCapabilities capabilities = {0}; + capabilities.can_tag_objects = 1; + jvmtiError error = jvmti->AddCapabilities(&capabilities); + if (error) { + fprintf(stderr, "ERROR: arthas vmtool JVMTI AddCapabilities failed!%u\n", error); + return JNI_FALSE; + } + return JNI_OK; } @@ -74,16 +83,9 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) extern "C" JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { - jvmtiCapabilities capabilities = {0}; - capabilities.can_tag_objects = 1; - jvmtiError error = jvmti->AddCapabilities(&capabilities); - if (error) { - printf("ERROR: JVMTI AddCapabilities failed!%u\n", error); - return JNI_FALSE; - } //这里用hashCode作为标记 jlong tag = getClassHashCode(env, klass); - error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, + jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); @@ -110,16 +112,9 @@ Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { - jvmtiCapabilities capabilities = {0}; - capabilities.can_tag_objects = 1; - jvmtiError error = jvmti->AddCapabilities(&capabilities); - if (error) { - printf("ERROR: JVMTI AddCapabilities failed!%u\n", error); - return JNI_FALSE; - } //这里用hashCode作为标记 jlong tag = getClassHashCode(env, klass); - error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, + jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); @@ -159,16 +154,9 @@ JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { - jvmtiCapabilities capabilities = {0}; - capabilities.can_tag_objects = 1; - jvmtiError error = jvmti->AddCapabilities(&capabilities); - if (error) { - printf("ERROR: JVMTI AddCapabilities failed!%u\n", error); - return JNI_FALSE; - } //这里用hashCode作为标记 jlong tag = getClassHashCode(env, klass); - error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, + jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); From aeede28cb97000b130f3679fd3bb1acbc25779bd Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 19:38:36 +0800 Subject: [PATCH 21/31] simplify tag generation mechanism --- .../src/main/java/arthas/VmTool.java | 8 +++--- .../src/main/native/src/jni-library.cpp | 25 +++++-------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index aaed0dc20..16ccd0d8f 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -41,12 +41,12 @@ public class VmTool implements VmToolMXBean { */ private static native String check0(); - private static native void forceGc0(); + private static synchronized native void forceGc0(); /** * 获取某个class在jvm中当前所有存活实例 */ - private static native T[] getInstances0(Class klass); + private static synchronized native T[] getInstances0(Class klass); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte @@ -61,14 +61,14 @@ public class VmTool implements VmToolMXBean { /** * 统计某个class在jvm中当前所有存活实例的总个数 */ - private static native long countInstances0(Class klass); + private static synchronized native long countInstances0(Class klass); /** * 获取所有已加载的类 * @param klass 这个参数必须是 Class.class * @return */ - private static native Class[] getAllLoadedClasses0(Class klass); + private static synchronized native Class[] getAllLoadedClasses0(Class klass); @Override public String check() { diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index a953dce29..6f9002f2a 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -6,6 +6,7 @@ static jvmtiEnv *jvmti; +static jlong tagCounter = 0; extern "C" int init_agent(JavaVM *vm, void *reserved) { @@ -57,19 +58,8 @@ Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { } extern "C" -jobject createJavaInstance(JNIEnv *env, jclass javaClass) { - //找到java类的构造方法 - jmethodID construct = env->GetMethodID(javaClass, "", "()V"); - //生成java类实例 - return env->NewObject(javaClass, construct, ""); -} - -extern "C" -jlong getClassHashCode(JNIEnv *env, jclass javaClass) { - //找到java类的hashCode方法 - jmethodID hashCodeMethod = env->GetMethodID(javaClass, "hashCode", "()I"); - //生成java类实例 - return env->CallLongMethod(javaClass, hashCodeMethod); +jlong getTag() { + return ++tagCounter; } extern "C" @@ -83,8 +73,7 @@ HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) extern "C" JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { - //这里用hashCode作为标记 - jlong tag = getClassHashCode(env, klass); + jlong tag = getTag(); jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { @@ -112,8 +101,7 @@ Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { - //这里用hashCode作为标记 - jlong tag = getClassHashCode(env, klass); + jlong tag = getTag(); jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { @@ -154,8 +142,7 @@ JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { - //这里用hashCode作为标记 - jlong tag = getClassHashCode(env, klass); + jlong tag = getTag(); jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { From d7a0fdf1e88ddd72dec4d0f08cf68b8a7e009297 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 19:41:26 +0800 Subject: [PATCH 22/31] remove useless code. --- arthas-vmtool/src/main/java/arthas/VmTool.java | 5 ----- arthas-vmtool/src/main/java/arthas/VmToolMXBean.java | 4 ---- arthas-vmtool/src/main/native/src/jni-library.cpp | 6 ------ 3 files changed, 15 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index 16ccd0d8f..a54974ba4 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -70,11 +70,6 @@ public class VmTool implements VmToolMXBean { */ private static synchronized native Class[] getAllLoadedClasses0(Class klass); - @Override - public String check() { - return check0(); - } - @Override public void forceGc() { forceGc0(); diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index 92df09be1..d1a18ab87 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -14,10 +14,6 @@ package arthas; * @author hengyunabc 2021-04-26 */ public interface VmToolMXBean { - /** - * 检测jni-lib是否正常,如果正常,应该输出OK - */ - public String check(); /** * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 6f9002f2a..9e64833b1 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -51,12 +51,6 @@ Java_arthas_VmTool_forceGc0(JNIEnv *env, jclass thisClass) { jvmti->ForceGarbageCollection(); } -extern "C" -JNIEXPORT jstring JNICALL -Java_arthas_VmTool_check0(JNIEnv *env, jclass thisClass) { - return env->NewStringUTF("OK"); -} - extern "C" jlong getTag() { return ++tagCounter; From f1d86b5c434728f6a793b4655ad98e5bf343a491 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 19:47:02 +0800 Subject: [PATCH 23/31] add getInstances interface test --- arthas-vmtool/pom.xml | 5 ++++ .../src/test/java/arthas/VmToolTest.java | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index 1e400d404..bacb2c15f 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -151,5 +151,10 @@ junit test + + org.assertj + assertj-core + test + \ No newline at end of file diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 16a7bac47..d8d3a2937 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -1,9 +1,13 @@ package arthas; +import org.assertj.core.api.Assertions; import org.junit.Test; import com.taobao.arthas.common.VmToolUtils; +import arthas.VmToolTest.AAA; +import arthas.VmToolTest.III; + import java.io.File; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicLong; @@ -144,4 +148,23 @@ public class VmToolTest { allLoadedClasses = null; } } + + interface III { + } + + class AAA implements III { + } + + @Test + public void test_getInstances_interface() { + AAA aaa = new AAA(); + VmTool vmtool = initVmTool(); + III[] interfaceInstances = vmtool.getInstances(III.class); + Assertions.assertThat(interfaceInstances.length).isEqualTo(1); + + AAA[] ObjectInstances = vmtool.getInstances(AAA.class); + Assertions.assertThat(ObjectInstances.length).isEqualTo(1); + + Assertions.assertThat(interfaceInstances[0]).isEqualTo(ObjectInstances[0]); + } } From d8ce0beeafedeef5b46af37a5f1ea8df896724a5 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 20:01:26 +0800 Subject: [PATCH 24/31] fix jni method return type --- arthas-vmtool/src/main/native/src/jni-library.cpp | 15 +++++++-------- .../src/test/java/arthas/VmToolTest.java | 11 ++++------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index 9e64833b1..d1dd5d430 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -72,7 +72,7 @@ Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { HeapObjectCallback, &tag); if (error) { printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); - return JNI_FALSE; + return NULL; } jint count = 0; @@ -80,7 +80,7 @@ Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { error = jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL); if (error) { printf("ERROR: JVMTI GetObjectsWithTags failed!%u\n", error); - return JNI_FALSE; + return NULL; } jobjectArray array = env->NewObjectArray(count, klass, NULL); @@ -100,7 +100,7 @@ Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) HeapObjectCallback, &tag); if (error) { printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); - return JNI_FALSE; + return -1; } jint count = 0; @@ -108,7 +108,7 @@ Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) error = jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL); if (error) { printf("ERROR: JVMTI GetObjectsWithTags failed!%u\n", error); - return JNI_FALSE; + return -1; } jlong sum = 0; @@ -128,7 +128,6 @@ JNIEXPORT jlong JNICALL Java_arthas_VmTool_getInstanceSize0 jvmtiError error = jvmti->GetObjectSize(instance, &size); if (error) { printf("ERROR: JVMTI GetObjectSize failed!%u\n", error); - return JNI_FALSE; } return size; } @@ -141,14 +140,14 @@ Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) HeapObjectCallback, &tag); if (error) { printf("ERROR: JVMTI IterateOverInstancesOfClass failed!%u\n", error); - return JNI_FALSE; + return -1; } jint count = 0; error = jvmti->GetObjectsWithTags(1, &tag, &count, NULL, NULL); if (error) { printf("ERROR: JVMTI GetObjectsWithTags failed!%u\n", error); - return JNI_FALSE; + return -1; } return count; } @@ -162,7 +161,7 @@ JNIEXPORT jobjectArray JNICALL Java_arthas_VmTool_getAllLoadedClasses0 jvmtiError error = jvmti->GetLoadedClasses(&count, &classes); if (error) { printf("ERROR: JVMTI GetLoadedClasses failed!\n"); - return JNI_FALSE; + return NULL; } jobjectArray array = env->NewObjectArray(count, kclass, NULL); diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index d8d3a2937..7cdc2f049 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -1,17 +1,14 @@ package arthas; +import java.io.File; +import java.lang.ref.WeakReference; +import java.util.concurrent.atomic.AtomicLong; + import org.assertj.core.api.Assertions; import org.junit.Test; import com.taobao.arthas.common.VmToolUtils; -import arthas.VmToolTest.AAA; -import arthas.VmToolTest.III; - -import java.io.File; -import java.lang.ref.WeakReference; -import java.util.concurrent.atomic.AtomicLong; - /** * 以下本地测试的jvm参数均为:-Xms128m -Xmx128m */ From e2e7061182c5bcad7699e5bfb5f9f217fe0732ee Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 22:49:04 +0800 Subject: [PATCH 25/31] vmtool support limit option. #1781 --- .../src/main/java/arthas/VmTool.java | 14 +++++-- .../src/main/java/arthas/VmToolMXBean.java | 8 +++- .../src/main/native/src/jni-library.cpp | 37 +++++++++++++++++- .../src/test/java/arthas/VmToolTest.java | 22 +++++++++++ .../command/monitor200/VmToolCommand.java | 16 +++++++- lib/libArthasJniLibrary-x64.dylib | Bin 53248 -> 52440 bytes spy/src/main/java/arthas/VmTool.java | 36 ++++++++--------- spy/src/main/java/arthas/VmToolMXBean.java | 12 +++--- 8 files changed, 114 insertions(+), 31 deletions(-) diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index a54974ba4..4e2775648 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -46,12 +46,12 @@ public class VmTool implements VmToolMXBean { /** * 获取某个class在jvm中当前所有存活实例 */ - private static synchronized native T[] getInstances0(Class klass); + private static synchronized native T[] getInstances0(Class klass, int limit); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte */ - private static native long sumInstanceSize0(Class klass); + private static synchronized native long sumInstanceSize0(Class klass); /** * 获取某个实例的占用内存,单位:Byte @@ -77,7 +77,15 @@ public class VmTool implements VmToolMXBean { @Override public T[] getInstances(Class klass) { - return getInstances0(klass); + return getInstances0(klass, -1); + } + + @Override + public T[] getInstances(Class klass, int limit) { + if (limit == 0) { + throw new IllegalArgumentException("limit can not be 0"); + } + return getInstances0(klass, limit); } @Override diff --git a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java index d1a18ab87..f21000115 100644 --- a/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java +++ b/arthas-vmtool/src/main/java/arthas/VmToolMXBean.java @@ -20,10 +20,16 @@ public interface VmToolMXBean { */ public void forceGc(); + public T[] getInstances(Class klass); + /** * 获取某个class在jvm中当前所有存活实例 + * @param + * @param klass + * @param limit 如果小于 0 ,则不限制 + * @return */ - public T[] getInstances(Class klass); + public T[] getInstances(Class klass, int limit); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte diff --git a/arthas-vmtool/src/main/native/src/jni-library.cpp b/arthas-vmtool/src/main/native/src/jni-library.cpp index d1dd5d430..c0bbc33ad 100644 --- a/arthas-vmtool/src/main/native/src/jni-library.cpp +++ b/arthas-vmtool/src/main/native/src/jni-library.cpp @@ -8,6 +8,30 @@ static jvmtiEnv *jvmti; static jlong tagCounter = 0; +struct LimitCounter { + jint currentCounter; + jint limitValue; + + void init(jint limit) { + currentCounter = 0; + limitValue = limit; + } + + void countDown() { + currentCounter++; + } + + bool allow() { + if (limitValue < 0) { + return true; + } + return limitValue > currentCounter; + } +}; + +// 每次 IterateOverInstancesOfClass 调用前需要先 init +static LimitCounter limitCounter = {0, 0}; + extern "C" int init_agent(JavaVM *vm, void *reserved) { jint rc; @@ -61,13 +85,20 @@ jvmtiIterationControl JNICALL HeapObjectCallback(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) { jlong *data = static_cast(user_data); *tag_ptr = *data; - return JVMTI_ITERATION_CONTINUE; + + limitCounter.countDown(); + if (limitCounter.allow()) { + return JVMTI_ITERATION_CONTINUE; + }else { + return JVMTI_ITERATION_ABORT; + } } extern "C" JNIEXPORT jobjectArray JNICALL -Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass) { +Java_arthas_VmTool_getInstances0(JNIEnv *env, jclass thisClass, jclass klass, jint limit) { jlong tag = getTag(); + limitCounter.init(limit); jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { @@ -96,6 +127,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_sumInstanceSize0(JNIEnv *env, jclass thisClass, jclass klass) { jlong tag = getTag(); + limitCounter.init(-1); jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { @@ -136,6 +168,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_arthas_VmTool_countInstances0(JNIEnv *env, jclass thisClass, jclass klass) { jlong tag = getTag(); + limitCounter.init(-1); jvmtiError error = jvmti->IterateOverInstancesOfClass(klass, JVMTI_HEAP_OBJECT_EITHER, HeapObjectCallback, &tag); if (error) { diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 7cdc2f049..3cc02f691 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -2,6 +2,7 @@ package arthas; import java.io.File; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.concurrent.atomic.AtomicLong; import org.assertj.core.api.Assertions; @@ -9,6 +10,8 @@ import org.junit.Test; import com.taobao.arthas.common.VmToolUtils; +import arthas.VmToolTest.LimitTest; + /** * 以下本地测试的jvm参数均为:-Xms128m -Xmx128m */ @@ -146,6 +149,25 @@ public class VmToolTest { } } + class LimitTest { + } + + @Test + public void test_getInstances_lmiit() { + VmTool vmtool = initVmTool(); + + ArrayList list = new ArrayList(); + for (int i = 0; i < 10; ++i) { + list.add(new LimitTest()); + } + LimitTest[] instances = vmtool.getInstances(LimitTest.class, 5); + Assertions.assertThat(instances).hasSize(5); + LimitTest[] instances2 = vmtool.getInstances(LimitTest.class, -1); + Assertions.assertThat(instances2).hasSize(10); + LimitTest[] instances3 = vmtool.getInstances(LimitTest.class, 1); + Assertions.assertThat(instances3).hasSize(1); + } + interface III { } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 05ab8cd12..e053b59f6 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -47,6 +47,8 @@ import arthas.VmTool; @Description(Constants.EXAMPLE + " vmtool --action getInstances --className demo.MathGame\n" + " vmtool --action getInstances --className demo.MathGame --express 'instances.length'\n" + + " vmtool --action getInstances --className demo.MathGame --express 'instances[0]'\n" + + " vmtool --action getInstances --className java.lang.String --limit 10\n" + " vmtool --action forceGc\n" + Constants.WIKI + Constants.WIKI_HOME + "vmtool") //@formatter:on @@ -64,6 +66,11 @@ public class VmToolCommand extends AnnotatedCommand { */ private int expand; + /** + * default value 10 + */ + private int limit; + private static String libPath; private static VmTool vmTool = null; @@ -117,6 +124,13 @@ public class VmToolCommand extends AnnotatedCommand { this.classLoaderClass = classLoaderClass; } + @Option(shortName = "l", longName = "limit") + @Description("Set the limit value of the getInstances action, default value is 10, set to -1 is unlimited") + @DefaultValue("10") + public void setLimit(int limit) { + this.limit = limit; + } + @Option(longName = "express", required = false) @Description("The ognl expression, default valueis `instances`.") public void setExpress(String express) { @@ -165,7 +179,7 @@ public class VmToolCommand extends AnnotatedCommand { process.end(-1, "Found more than one class: " + matchedClasses + "."); return; } else { - Object[] instances = vmToolInstance().getInstances(matchedClasses.get(0)); + Object[] instances = vmToolInstance().getInstances(matchedClasses.get(0), limit); Object value = instances; if (express != null) { Express unpooledExpress = ExpressFactory.unpooledExpress(classLoader); diff --git a/lib/libArthasJniLibrary-x64.dylib b/lib/libArthasJniLibrary-x64.dylib index 5547993f54f3f17dad8737f111553030136e765f..bf5f6ef13061928e18601c3bf688eb9310e22a10 100644 GIT binary patch literal 52440 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 literal 53248 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 diff --git a/spy/src/main/java/arthas/VmTool.java b/spy/src/main/java/arthas/VmTool.java index d530a06d5..4e2775648 100644 --- a/spy/src/main/java/arthas/VmTool.java +++ b/spy/src/main/java/arthas/VmTool.java @@ -41,17 +41,17 @@ public class VmTool implements VmToolMXBean { */ private static native String check0(); - private static native void forceGc0(); + private static synchronized native void forceGc0(); /** * 获取某个class在jvm中当前所有存活实例 */ - private static native T[] getInstances0(Class klass); + private static synchronized native T[] getInstances0(Class klass, int limit); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte */ - private static native long sumInstanceSize0(Class klass); + private static synchronized native long sumInstanceSize0(Class klass); /** * 获取某个实例的占用内存,单位:Byte @@ -61,24 +61,14 @@ public class VmTool implements VmToolMXBean { /** * 统计某个class在jvm中当前所有存活实例的总个数 */ - private static native long countInstances0(Class klass); + private static synchronized native long countInstances0(Class klass); /** * 获取所有已加载的类 + * @param klass 这个参数必须是 Class.class + * @return */ - private static native Class[] getAllLoadedClasses0(); - - /** - * 包括小类型(如int) - */ - public static Class[] getAllClasses() { - return getInstances0(Class.class); - } - - @Override - public String check() { - return check0(); - } + private static synchronized native Class[] getAllLoadedClasses0(Class klass); @Override public void forceGc() { @@ -87,7 +77,15 @@ public class VmTool implements VmToolMXBean { @Override public T[] getInstances(Class klass) { - return getInstances0(klass); + return getInstances0(klass, -1); + } + + @Override + public T[] getInstances(Class klass, int limit) { + if (limit == 0) { + throw new IllegalArgumentException("limit can not be 0"); + } + return getInstances0(klass, limit); } @Override @@ -107,7 +105,7 @@ public class VmTool implements VmToolMXBean { @Override public Class[] getAllLoadedClasses() { - return getAllLoadedClasses0(); + return getAllLoadedClasses0(Class.class); } } diff --git a/spy/src/main/java/arthas/VmToolMXBean.java b/spy/src/main/java/arthas/VmToolMXBean.java index 92df09be1..f21000115 100644 --- a/spy/src/main/java/arthas/VmToolMXBean.java +++ b/spy/src/main/java/arthas/VmToolMXBean.java @@ -14,20 +14,22 @@ package arthas; * @author hengyunabc 2021-04-26 */ public interface VmToolMXBean { - /** - * 检测jni-lib是否正常,如果正常,应该输出OK - */ - public String check(); /** * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection */ public void forceGc(); + public T[] getInstances(Class klass); + /** * 获取某个class在jvm中当前所有存活实例 + * @param + * @param klass + * @param limit 如果小于 0 ,则不限制 + * @return */ - public T[] getInstances(Class klass); + public T[] getInstances(Class klass, int limit); /** * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte From 3170a92b565b59c037fe501accc7c0ef4187f0d4 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 7 May 2021 23:34:28 +0800 Subject: [PATCH 26/31] vmtool command support libPath --- .../core/command/monitor200/VmToolCommand.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index e053b59f6..35e46ec0e 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -71,7 +71,8 @@ public class VmToolCommand extends AnnotatedCommand { */ private int limit; - private static String libPath; + private String libPath; + private static String defaultLibPath; private static VmTool vmTool = null; static { @@ -83,7 +84,7 @@ public class VmToolCommand extends AnnotatedCommand { File bootJarPath = new File(codeSource.getLocation().toURI().getSchemeSpecificPart()); File soFile = new File(bootJarPath.getParentFile(), "lib" + File.separator + libName); if (soFile.exists()) { - libPath = soFile.getAbsolutePath(); + defaultLibPath = soFile.getAbsolutePath(); } } catch (Throwable e) { logger.error("can not find VmTool so", e); @@ -131,6 +132,12 @@ public class VmToolCommand extends AnnotatedCommand { this.limit = limit; } + @Option(longName = "libPath") + @Description("The specify lib path.") + public void setLibPath(String path) { + libPath = path; + } + @Option(longName = "express", required = false) @Description("The ognl expression, default valueis `instances`.") public void setExpress(String express) { @@ -138,7 +145,7 @@ public class VmToolCommand extends AnnotatedCommand { } public enum VmToolAction { - getInstances, forceGc, load + getInstances, forceGc } @Override @@ -230,6 +237,9 @@ public class VmToolCommand extends AnnotatedCommand { if (vmTool != null) { return vmTool; } else { + if (libPath == null) { + libPath = defaultLibPath; + } vmTool = VmTool.getInstance(libPath); } return vmTool; From fc707109b172395958bb9e8d8b9722ba393dd10f Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 11 May 2021 16:53:10 +0800 Subject: [PATCH 27/31] improve vmtool search class. --- arthas-vmtool/README_CN.md | 62 ------------------- .../command/monitor200/VmToolCommand.java | 14 +++-- 2 files changed, 10 insertions(+), 66 deletions(-) delete mode 100644 arthas-vmtool/README_CN.md diff --git a/arthas-vmtool/README_CN.md b/arthas-vmtool/README_CN.md deleted file mode 100644 index 4ea4b8795..000000000 --- a/arthas-vmtool/README_CN.md +++ /dev/null @@ -1,62 +0,0 @@ -##step1 在您的pom.xml中增加profile配置 -``` - - - - macos - - - mac - - - - macos - - - - - - linux - - - linux - - - - linux - - - - - - windows - - - windows - - - - windows - - - -``` -##step2 在您的pom.xml中引入依赖 -PS:一定要配置好profile,不然无法自动生成``配置。 -``` - - com.taobao.arthas - mana-pool-analyzer - ${arthas.vision} - ${os_family}-${os.arch} - -``` - -##step3 如果没有合适的版本 -1. 如果是32位的操作系统,不好意思,目前暂不支持。 - -2. 如果是64位操作系统,请先尝试`mvn clean compile package install -DskipTests=true -U`把依赖安装到本地; - -3. 如果报错,请先确保您本地的g++编译器能够正常工作,再重新尝试`mvn clean compile package install -DskipTests=true -U`; - -如有问题请联系`1936978077@qq.com`。 diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 35e46ec0e..6f7dd468d 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -48,7 +48,9 @@ import arthas.VmTool; + " vmtool --action getInstances --className demo.MathGame\n" + " vmtool --action getInstances --className demo.MathGame --express 'instances.length'\n" + " vmtool --action getInstances --className demo.MathGame --express 'instances[0]'\n" + + " vmtool --action getInstances --className demo.MathGame -x 2\n" + " vmtool --action getInstances --className java.lang.String --limit 10\n" + + " vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext\n" + " vmtool --action forceGc\n" + Constants.WIKI + Constants.WIKI_HOME + "vmtool") //@formatter:on @@ -62,7 +64,7 @@ public class VmToolCommand extends AnnotatedCommand { private String hashCode = null; private String classLoaderClass; /** - * default value 2 + * default value 1 */ private int expand; @@ -107,8 +109,8 @@ public class VmToolCommand extends AnnotatedCommand { } @Option(shortName = "x", longName = "expand") - @Description("Expand level of object (2 by default)") - @DefaultValue("2") + @Description("Expand level of object (1 by default)") + @DefaultValue("1") public void setExpand(int expand) { this.expand = expand; } @@ -154,6 +156,10 @@ public class VmToolCommand extends AnnotatedCommand { Instrumentation inst = process.session().getInstrumentation(); if (VmToolAction.getInstances.equals(action)) { + if (className == null) { + process.end(-1, "The className option cannot be empty!"); + return; + } ClassLoader classLoader = ClassLoader.getSystemClassLoader(); if (hashCode == null && classLoaderClass != null) { List matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, @@ -177,7 +183,7 @@ public class VmToolCommand extends AnnotatedCommand { } List> matchedClasses = new ArrayList>( - SearchUtils.searchClass(inst, className, false, hashCode)); + SearchUtils.searchClassOnly(inst, className, false, hashCode)); int matchedClassSize = matchedClasses.size(); if (matchedClassSize == 0) { process.end(-1, "Can not find class by class name: " + className + "."); From 88b31d68efcbc6e5288218a6554b8c8bacb87a0f Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 11 May 2021 17:07:24 +0800 Subject: [PATCH 28/31] add vmtool doc. #1781 --- site/src/site/sphinx/advanced-use.md | 2 +- site/src/site/sphinx/commands.md | 1 + site/src/site/sphinx/en/advanced-use.md | 2 +- site/src/site/sphinx/en/commands.md | 1 + site/src/site/sphinx/en/vmtool.md | 70 ++++++++++++++++++++++++ site/src/site/sphinx/vmtool.md | 71 +++++++++++++++++++++++++ 6 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 site/src/site/sphinx/en/vmtool.md create mode 100644 site/src/site/sphinx/vmtool.md diff --git a/site/src/site/sphinx/advanced-use.md b/site/src/site/sphinx/advanced-use.md index bb9c0c7ee..c17df1986 100644 --- a/site/src/site/sphinx/advanced-use.md +++ b/site/src/site/sphinx/advanced-use.md @@ -35,7 +35,7 @@ * [ognl](ognl.md)——执行ognl表达式 * [mbean](mbean.md)——查看 Mbean 的信息 * [heapdump](heapdump.md)——dump java heap, 类似jmap命令的heap dump功能 - +* [vmtool](vmtool.md)——从jvm里查询对象,执行forceGc ## class/classloader相关 diff --git a/site/src/site/sphinx/commands.md b/site/src/site/sphinx/commands.md index 9a6e06b59..c51bcb949 100644 --- a/site/src/site/sphinx/commands.md +++ b/site/src/site/sphinx/commands.md @@ -18,6 +18,7 @@ * [sm](sm.md) * [dump](dump.md) * [heapdump](heapdump.md) +* [vmtool](vmtool.md) * [jad](jad.md) * [classloader](classloader.md) diff --git a/site/src/site/sphinx/en/advanced-use.md b/site/src/site/sphinx/en/advanced-use.md index 2479f14be..dba45d449 100644 --- a/site/src/site/sphinx/en/advanced-use.md +++ b/site/src/site/sphinx/en/advanced-use.md @@ -33,7 +33,7 @@ Advanced Usage * [ognl](ognl.md) - execute ognl expression * [mbean](mbean.md) - show Mbean information * [heapdump](heapdump.md) - dump java heap in hprof binary format, like `jmap` - +* [vmtool](vmtool.md) - jvm tool, getInstances in jvm, forceGc ## class/classloader * [sc](sc.md) - check the info for the classes loaded by JVM diff --git a/site/src/site/sphinx/en/commands.md b/site/src/site/sphinx/en/commands.md index e997ca785..a4a3eeae3 100644 --- a/site/src/site/sphinx/en/commands.md +++ b/site/src/site/sphinx/en/commands.md @@ -18,6 +18,7 @@ All Commands * [sm](sm.md) * [dump](dump.md) * [heapdump](heapdump.md) +* [vmtool](vmtool.md) * [jad](jad.md) * [classloader](classloader.md) diff --git a/site/src/site/sphinx/en/vmtool.md b/site/src/site/sphinx/en/vmtool.md new file mode 100644 index 000000000..2e6cb5a3d --- /dev/null +++ b/site/src/site/sphinx/en/vmtool.md @@ -0,0 +1,70 @@ +vmtool +=== + +> @since 3.5.1 +[`vmtool` online tutorial](https://arthas.aliyun.com/doc/arthas-tutorials.html?language=en&id=command-vmtool) + +`vmtool` uses the `JVMTI` to support `getInstances` in jvm and `forceGc`. + +* [JVM Tool Interface](https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html) + +### getInstances + +```bash +vmtool --action getInstances --className java.lang.String --limit 10 +``` + +> Through the `--limit` parameter, you can limit the number of return values to avoid pressure on the JVM when obtaining large data. The default value of limit is 10. + +### Specify classloader name + +```bash +vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext +``` + + +### Specify classloader hash + +The classloader that loads the class can be found through the `sc` command. + +```bash +$ sc -d org.springframework.context.ApplicationContext + class-info org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext + code-source file:/private/tmp/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spring-boot-1.5.13.RELEASE.jar!/ + name org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext +... + class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@19469ea2 + +-sun.misc.Launcher$AppClassLoader@75b84c92 + +-sun.misc.Launcher$ExtClassLoader@4f023edb + classLoaderHash 19469ea2 +``` + +Then use the `-c`/`--classloader` parameter to specify: + +```bash +vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext +``` + +### Specify the number of expanded layers of returned results + +> The return result of the `getInstances` action is bound to the `instances` variable, which is an array. + +> The expansion level of the result can be specified by the `-x`/`--expand` parameter, the default value is 1. + +```bash +vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext -x 2 +``` + +### Execute expression + +> The return result of the `getInstances` action is bound to the `instances` variable, which is an array. The specified expression can be executed through the `--express` parameter. + +```bash +vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext --express'instances[0].getBeanDefinitionNames()' +``` + +### Force GC + +```bash +vmtool --action forceGc +``` \ No newline at end of file diff --git a/site/src/site/sphinx/vmtool.md b/site/src/site/sphinx/vmtool.md new file mode 100644 index 000000000..83bb991ca --- /dev/null +++ b/site/src/site/sphinx/vmtool.md @@ -0,0 +1,71 @@ +vmtool +=== + +> @since 3.5.1 + +[`vmtool`在线教程](https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=command-vmtool) + +`vmtool` 利用`JVMTI`接口,实现查询内存对象,强制GC等功能。 + +* [JVM Tool Interface](https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html) + +### 获取对象 + +```bash +vmtool --action getInstances --className java.lang.String --limit 10 +``` + +> 通过 `--limit`参数,可以限制返回值数量,避免获取超大数据时对JVM造成压力。默认值是10。 + +### 指定 classloader name + +```bash +vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext +``` + + +### 指定 classloader hash + +可以通过`sc`命令查找到加载class的 classloader。 + +```bash +$ sc -d org.springframework.context.ApplicationContext + class-info org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext + code-source file:/private/tmp/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spring-boot-1.5.13.RELEASE.jar!/ + name org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext +... + class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@19469ea2 + +-sun.misc.Launcher$AppClassLoader@75b84c92 + +-sun.misc.Launcher$ExtClassLoader@4f023edb + classLoaderHash 19469ea2 +``` + +然后用`-c`/`--classloader` 参数指定: + +```bash +vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext +``` + +### 指定返回结果展开层数 + +> `getInstances` action返回结果绑定到`instances`变量上,它是数组。 + +> 通过 `-x`/`--expand` 参数可以指定结果的展开层次,默认值是1。 + +```bash +vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext -x 2 +``` + +### 执行表达式 + +> `getInstances` action返回结果绑定到`instances`变量上,它是数组。可以通过`--express`参数执行指定的表达式。 + +```bash +vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()' +``` + +### 强制GC + +```bash +vmtool --action forceGc +``` \ No newline at end of file From 5c418545f4a4589e6f8d2e68be703146ed02a61f Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 11 May 2021 17:34:53 +0800 Subject: [PATCH 29/31] update vmtool so --- lib/libArthasJniLibrary-x64.dll | Bin 86115 -> 85695 bytes lib/libArthasJniLibrary-x64.dylib | Bin 52440 -> 52440 bytes lib/libArthasJniLibrary-x64.so | Bin 22360 -> 18488 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/libArthasJniLibrary-x64.dll b/lib/libArthasJniLibrary-x64.dll index b9c983aeecd74c8dc313ec75569bb70e50ff47f3..e53a26f3e9925792ec2e1f256e2cb9ee0c36d9ba 100644 GIT binary patch delta 17375 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 z zJ$Nap5_Ae<{U9UYaHS#0!x*N)s|Q!HuN!qSLC94Sj7$QeE)7Oz0I|*vM&1M^g|s`lu0~|LDuNw2jYc(YCd$=X$ZuSwWG1~=LV5MqnPQGgI{N8C zJeI%yn_g5e@VdcwT#MxF+89|Lw#TI6?gBUX!@uFS9FE)a59h;q)9H2j3ti&C@KK+RlM%cs~)1TNPaUb27?nqz~JK^`~j>l#81F&(TgpTt}cQnfEUa*}* z2z_D;lQhKi^(dn<2IWw*C7Fa(trZ{>BW z9P(EBhoa*0R{lnn$&PRp(}sPEP_`i`={-FZ)P=sFQobbPe%0nj{PXNss$#x4>r~Pe zt0)lXVn>fK=sobi_m;p|&`3BiIB-S`3SHIFcEr z+_5);EhK>AJUJ3^ep=>_5}(vr!V99nKPmH{fM-)3RY@$>VT@)GV##7hV=_Y)J2pqN zM;-C8QWsMvba_nX_Y<#HOZeCr@Q=v+9^yN7k?>KS!EciJe-IxLC*i|m!9OJPyND0% zD&d3G;Md8#6a16$5}exw@EVzajri*_-!~5Y3XLT5D)AjM-?J9gd7n2&UTcSJXtI($Uljr;OUsEdkXCfAtxvs{PgEL{yXfRR>jd z{;DPkipwahc${@SnoRRZbE9`;CNncz;tzPFuMyGKJAO-MiM(F3DC_eY@yWbNK0kus^#E|Xq{`tjR}tHVJsbww}RjRTv&s&!ZUu7V@xs&bG)3& zR$871PXG4+g1G2?0v$VFRyr!nAreuL{jgTWXkWu@cmX;ULLaCR|>mu2r z58lOikw+47)o;T=5g7g790R*Cz2zOqcKB^luMdH=E08aNw0Iv%%TDiq^u1p>E%)O`=6O))pufGABy<2lf+kV$fUmd-SmYDF0I z5NlMplm~gB!6$wS>vGK=x|tAP1kfLw~q{Sb&5 zJ_S;zl@NvM%Rmf%q;z&wO)YwCS2#p}BeyE1m7c9hv*T+WOS2eJqfa2$rvl0GYo)fO zK$83uNXSMYI>jdCko7DM=y?%HiNf;RK$;aZdMJ*%DVExojz=?)oK1>R{6e}AuE4e+ z;K_cOLRT`7CdKq*1K9%o6m}}|U;m8?nQ@R&W=AQI5_(4+NVAoW+)Vh?sIa#QaxKsq z(Cz?|qtO055Tjxfegg=70?I!Ha$2#Oe+@+Ez37TUaq+VG#Vdf|$u%e)euPk)BCl=$ zaXZduGOZ;FuQX_<2>6!iMFROW0LX5|h;9esQq0&KAfzPVtp&)Z{!Cpue_mxN?nV`g z+1f-xYX1PBLfA@*@ClfAl8j$94w1^T#nnQgLeXK!H2P(z|5+f16v1M6Q=$y9ntqzm zq!@<*LWPQ%83m*Q3grmZl*@aWQHqC7Lh%<8$j~Q{)ATElB85Yb0NJfTwx?rhmne+A z1tFcnq5VLHDP&wgHsV=Jez+jBZXo1I!2C7pr7)JNMT8W3h6Ayf70?7gZHk#L1wubA z2pFpaQmyFqAP{=x6)^u45Tn9;Gms9f%Rqj-52VRapUraf{s*j8A?_gsifto7hsCB? zAXz|~6wVHI+{kA7o>NFv(NF<|Ud#oo*8*`l^15RQ*uc^v2)Mruh#6QQ2j2vOF$c-) z1Ja@h%wZtSkbxbk2*US3wkXVA2clMNkew|V@YdUfy5g^6Kn^MV9}UE+nDS{rw)<7j zt*)yrL(eUKhp-ncDh6Z#8W_ex^rF=sg(BNpmSMp-6vi4M)a+LcN#Qvl?Fz&R)1?~S1f_AusF&V(|AO#05mB7{<3iDilNg9S8U;cO%4EoEN)rov&x3#z1_{QmEQ$o2R8&)se{I*5$sS5?lF zMPj@nftS682!L$i1Y&|gD?-O?_XRyAGs!!;j&R% zPWtmIm)4e6mX%Ypl$K`iFSvK92e6*(=6vl}P5*9zA}y5(E&mG$3V}b)L`5Rrs@2;G z`4W_e%51;Y)PG3JTde#CdHiDz7Uf|7PYHRex&KQ#OaGEYmL+Hd$o=nA^H$UUeP7wI z*RF+jCOLJLnR}~+TeJVx3HrnI75*TpeCr@yu@Jlp9k2Ce$&PV@*g#79HI(nOcU>RM N{?2x-8^%T@{C`qP0L1_R diff --git a/lib/libArthasJniLibrary-x64.dylib b/lib/libArthasJniLibrary-x64.dylib index bf5f6ef13061928e18601c3bf688eb9310e22a10..d2d9430fc379f36aa5ca85b68e5f7f876e2387e9 100644 GIT binary patch delta 91 zcmcaHlljI><_+~MLPe!{d8tME<@rU~`iVs)8HvS{C$qRtzQ(dh*`oc2l0>L=%cc#b sTc^IfU~a^~z@Pxcj6lr5&&9yT&oy~As~!_$+vL+gDur?LZ`QlV0290(<^TWy delta 93 zcmcaHlljI><_+~MA{nW9>6N86m;PNZIgg{>^yvV19;5&O diff --git a/lib/libArthasJniLibrary-x64.so b/lib/libArthasJniLibrary-x64.so index b24706f3b19cbf56b365a48c09bd3ddf03e8a1e1..b90076e728c95f47ae46761376ff7f3d887a991a 100644 GIT binary patch literal 18488 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 T`VL%9|4TR967w_#4Hf?jM~Lup literal 22360 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 Ja4EP@@!yJ;IS~K= From 14d7efab1eb254fdba377db2edd8ffb939e67d02 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 13 May 2021 11:52:08 +0800 Subject: [PATCH 30/31] update vmtool.md --- site/src/site/sphinx/en/vmtool.md | 14 +++++++++++++- site/src/site/sphinx/vmtool.md | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/site/src/site/sphinx/en/vmtool.md b/site/src/site/sphinx/en/vmtool.md index 2e6cb5a3d..b30dde9db 100644 --- a/site/src/site/sphinx/en/vmtool.md +++ b/site/src/site/sphinx/en/vmtool.md @@ -11,7 +11,19 @@ vmtool ### getInstances ```bash -vmtool --action getInstances --className java.lang.String --limit 10 +$ vmtool --action getInstances --className java.lang.String --limit 10 +@String[][ + @String[com/taobao/arthas/core/shell/session/Session], + @String[com.taobao.arthas.core.shell.session.Session], + @String[com/taobao/arthas/core/shell/session/Session], + @String[com/taobao/arthas/core/shell/session/Session], + @String[com/taobao/arthas/core/shell/session/Session.class], + @String[com/taobao/arthas/core/shell/session/Session.class], + @String[com/taobao/arthas/core/shell/session/Session.class], + @String[com/], + @String[java/util/concurrent/ConcurrentHashMap$ValueIterator], + @String[java/util/concurrent/locks/LockSupport], +] ``` > Through the `--limit` parameter, you can limit the number of return values to avoid pressure on the JVM when obtaining large data. The default value of limit is 10. diff --git a/site/src/site/sphinx/vmtool.md b/site/src/site/sphinx/vmtool.md index 83bb991ca..59ab1f514 100644 --- a/site/src/site/sphinx/vmtool.md +++ b/site/src/site/sphinx/vmtool.md @@ -12,7 +12,19 @@ vmtool ### 获取对象 ```bash -vmtool --action getInstances --className java.lang.String --limit 10 +$ vmtool --action getInstances --className java.lang.String --limit 10 +@String[][ + @String[com/taobao/arthas/core/shell/session/Session], + @String[com.taobao.arthas.core.shell.session.Session], + @String[com/taobao/arthas/core/shell/session/Session], + @String[com/taobao/arthas/core/shell/session/Session], + @String[com/taobao/arthas/core/shell/session/Session.class], + @String[com/taobao/arthas/core/shell/session/Session.class], + @String[com/taobao/arthas/core/shell/session/Session.class], + @String[com/], + @String[java/util/concurrent/ConcurrentHashMap$ValueIterator], + @String[java/util/concurrent/locks/LockSupport], +] ``` > 通过 `--limit`参数,可以限制返回值数量,避免获取超大数据时对JVM造成压力。默认值是10。 From 32e7bfa6b8b8c644acd8e7817bf6f858a273030f Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 13 May 2021 20:21:35 +0800 Subject: [PATCH 31/31] vmtool lib support reload/reattach. --- arthas-vmtool/pom.xml | 2 +- .../src/main/java/arthas/VmTool.java | 5 - .../src/main/java/arthas/package-info.java | 6 +- .../src/test/java/arthas/VmToolTest.java | 16 +-- core/pom.xml | 5 + .../command/monitor200/VmToolCommand.java | 22 ++++ spy/src/main/java/arthas/VmTool.java | 111 ------------------ spy/src/main/java/arthas/VmToolMXBean.java | 53 --------- spy/src/main/java/arthas/package-info.java | 8 -- 9 files changed, 35 insertions(+), 193 deletions(-) delete mode 100644 spy/src/main/java/arthas/VmTool.java delete mode 100644 spy/src/main/java/arthas/VmToolMXBean.java delete mode 100644 spy/src/main/java/arthas/package-info.java diff --git a/arthas-vmtool/pom.xml b/arthas-vmtool/pom.xml index bacb2c15f..9766bf3c4 100644 --- a/arthas-vmtool/pom.xml +++ b/arthas-vmtool/pom.xml @@ -121,7 +121,7 @@ -o - -o ${project.build.directory}/classes/${lib_name} + -o ${project.build.directory}/${lib_name} diff --git a/arthas-vmtool/src/main/java/arthas/VmTool.java b/arthas-vmtool/src/main/java/arthas/VmTool.java index 4e2775648..866d47ecb 100644 --- a/arthas-vmtool/src/main/java/arthas/VmTool.java +++ b/arthas-vmtool/src/main/java/arthas/VmTool.java @@ -36,11 +36,6 @@ public class VmTool implements VmToolMXBean { return instance; } - /** - * 检测jni-lib是否正常,如果正常,应该输出OK - */ - private static native String check0(); - private static synchronized native void forceGc0(); /** diff --git a/arthas-vmtool/src/main/java/arthas/package-info.java b/arthas-vmtool/src/main/java/arthas/package-info.java index ba203103d..ddf184f18 100644 --- a/arthas-vmtool/src/main/java/arthas/package-info.java +++ b/arthas-vmtool/src/main/java/arthas/package-info.java @@ -1,6 +1,2 @@ -/** - *
- * 修改后要同步到 spy/src/main/java 。
- * 
- */ + package arthas; diff --git a/arthas-vmtool/src/test/java/arthas/VmToolTest.java b/arthas-vmtool/src/test/java/arthas/VmToolTest.java index 3cc02f691..8a573f7e1 100644 --- a/arthas-vmtool/src/test/java/arthas/VmToolTest.java +++ b/arthas-vmtool/src/test/java/arthas/VmToolTest.java @@ -10,12 +10,16 @@ import org.junit.Test; import com.taobao.arthas.common.VmToolUtils; -import arthas.VmToolTest.LimitTest; - /** * 以下本地测试的jvm参数均为:-Xms128m -Xmx128m */ public class VmToolTest { + private VmTool initVmTool() { + File path = new File(VmTool.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile(); + + String libPath = new File(path, VmToolUtils.detectLibName()).getAbsolutePath(); + return VmTool.getInstance(libPath); + } /** * macbook上运行结果如下 @@ -57,14 +61,6 @@ public class VmToolTest { } } - private VmTool initVmTool() { - String path = VmTool.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - System.err.println(path); - - String libPath = new File(path, VmToolUtils.detectLibName()).getAbsolutePath(); - return VmTool.getInstance(libPath); - } - @Test public void testGetInstancesMemoryLeak() { //这里睡20s是为了方便用jprofiler连接上进程 diff --git a/core/pom.xml b/core/pom.xml index 507c6c312..f3119e240 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -120,6 +120,11 @@ arthas-common ${project.version} + + com.taobao.arthas + arthas-vmtool + ${project.version} + com.alibaba bytekit-core diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 6f7dd468d..0928e12b3 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -1,6 +1,8 @@ package com.taobao.arthas.core.command.monitor200; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.lang.instrument.Instrumentation; import java.security.CodeSource; import java.util.ArrayList; @@ -11,6 +13,7 @@ import java.util.Set; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; +import com.taobao.arthas.common.IOUtils; import com.taobao.arthas.common.VmToolUtils; import com.taobao.arthas.core.command.Constants; import com.taobao.arthas.core.command.express.Express; @@ -246,6 +249,25 @@ public class VmToolCommand extends AnnotatedCommand { if (libPath == null) { libPath = defaultLibPath; } + + // 尝试把lib文件复制到临时文件里,避免多次attach时出现 Native Library already loaded in another classloader + FileOutputStream tmpLibOutputStream = null; + FileInputStream libInputStream = null; + try { + File tmpLibFile = File.createTempFile(VmTool.JNI_LIBRARY_NAME, null); + tmpLibOutputStream = new FileOutputStream(tmpLibFile); + libInputStream = new FileInputStream(new File(libPath)); + + IOUtils.copy(libInputStream, tmpLibOutputStream); + libPath = tmpLibFile.getAbsolutePath(); + logger.debug("copy {} to {}", libPath, tmpLibFile); + } catch (Throwable e) { + logger.error("try to copy lib error! libPath: {}", libPath, e); + } finally { + IOUtils.close(libInputStream); + IOUtils.close(tmpLibOutputStream); + } + vmTool = VmTool.getInstance(libPath); } return vmTool; diff --git a/spy/src/main/java/arthas/VmTool.java b/spy/src/main/java/arthas/VmTool.java deleted file mode 100644 index 4e2775648..000000000 --- a/spy/src/main/java/arthas/VmTool.java +++ /dev/null @@ -1,111 +0,0 @@ -package arthas; - -/** - * @author ZhangZiCheng 2021-02-12 - * @author hengyunabc 2021-04-26 - * @since 3.5.1 - */ -public class VmTool implements VmToolMXBean { - - /** - * 不要修改jni-lib的名称 - */ - public final static String JNI_LIBRARY_NAME = "ArthasJniLibrary"; - - private static VmTool instance; - - private VmTool() { - } - - public static VmTool getInstance() { - return getInstance(null); - } - - public static synchronized VmTool getInstance(String libPath) { - if (instance != null) { - return instance; - } - - if (libPath == null) { - System.loadLibrary(JNI_LIBRARY_NAME); - } else { - System.load(libPath); - } - - instance = new VmTool(); - return instance; - } - - /** - * 检测jni-lib是否正常,如果正常,应该输出OK - */ - private static native String check0(); - - private static synchronized native void forceGc0(); - - /** - * 获取某个class在jvm中当前所有存活实例 - */ - private static synchronized native T[] getInstances0(Class klass, int limit); - - /** - * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte - */ - private static synchronized native long sumInstanceSize0(Class klass); - - /** - * 获取某个实例的占用内存,单位:Byte - */ - private static native long getInstanceSize0(Object instance); - - /** - * 统计某个class在jvm中当前所有存活实例的总个数 - */ - private static synchronized native long countInstances0(Class klass); - - /** - * 获取所有已加载的类 - * @param klass 这个参数必须是 Class.class - * @return - */ - private static synchronized native Class[] getAllLoadedClasses0(Class klass); - - @Override - public void forceGc() { - forceGc0(); - } - - @Override - public T[] getInstances(Class klass) { - return getInstances0(klass, -1); - } - - @Override - public T[] getInstances(Class klass, int limit) { - if (limit == 0) { - throw new IllegalArgumentException("limit can not be 0"); - } - return getInstances0(klass, limit); - } - - @Override - public long sumInstanceSize(Class klass) { - return sumInstanceSize0(klass); - } - - @Override - public long getInstanceSize(Object instance) { - return getInstanceSize0(instance); - } - - @Override - public long countInstances(Class klass) { - return countInstances0(klass); - } - - @Override - public Class[] getAllLoadedClasses() { - return getAllLoadedClasses0(Class.class); - } - -} diff --git a/spy/src/main/java/arthas/VmToolMXBean.java b/spy/src/main/java/arthas/VmToolMXBean.java deleted file mode 100644 index f21000115..000000000 --- a/spy/src/main/java/arthas/VmToolMXBean.java +++ /dev/null @@ -1,53 +0,0 @@ -package arthas; - -/** - * VmTool interface for JMX server. How to register VmTool MBean: - * - *
- * {@code
- *     ManagementFactory.getPlatformMBeanServer().registerMBean(
- *             VmTool.getInstance(),
- *             new ObjectName("arthas:type=VmTool")
- *     );
- * }
- * 
- * @author hengyunabc 2021-04-26 - */ -public interface VmToolMXBean { - - /** - * https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#ForceGarbageCollection - */ - public void forceGc(); - - public T[] getInstances(Class klass); - - /** - * 获取某个class在jvm中当前所有存活实例 - * @param - * @param klass - * @param limit 如果小于 0 ,则不限制 - * @return - */ - public T[] getInstances(Class klass, int limit); - - /** - * 统计某个class在jvm中当前所有存活实例的总占用内存,单位:Byte - */ - public long sumInstanceSize(Class klass); - - /** - * 获取某个实例的占用内存,单位:Byte - */ - public long getInstanceSize(Object instance); - - /** - * 统计某个class在jvm中当前所有存活实例的总个数 - */ - public long countInstances(Class klass); - - /** - * 获取所有已加载的类 - */ - public Class[] getAllLoadedClasses(); -} diff --git a/spy/src/main/java/arthas/package-info.java b/spy/src/main/java/arthas/package-info.java deleted file mode 100644 index 8762944ed..000000000 --- a/spy/src/main/java/arthas/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - *
- * copy from arthas-vmtool/src/main/java 。
- * 因为动态链接库只能被加载一次,只能使用一份代码。放在spy jar里保证只有一份。
- * TODO 当arthas本身版本升级时,已append 到bootstrap classloader的spy jar不能升级,VmTool的接口可以会调用失败。
- * 
- */ -package arthas;