Merge branch 'master' into master

pull/1879/head
yangxb2010000 2 years ago committed by GitHub
commit 3e9269b067
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,22 @@
name: auto prettier
on:
push:
paths:
- 'site/**'
jobs:
prettier:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Prettify code
uses: creyD/prettier_action@v4.3
with:
prettier_options: --config ./site/.prettierrc.json --ignore-path ./site/.prettierignore --write ./site

@ -0,0 +1,261 @@
name: build async-profiler
on:
workflow_dispatch:
inputs:
async-profiler-tag-name:
description: 'Enter the async-profiler tag name in https://github.com/async-profiler/async-profiler/tags(e.g. v2.9) please.'
type: string
required: true
jobs:
build-mac:
runs-on: macos-12
if: ${{ inputs.async-profiler-tag-name }}
steps:
# 检出 async-profiler/async-profiler 项目指定的 tag
- uses: actions/checkout@v3
with:
repository: async-profiler/async-profiler
fetch-depth: 0
- name: Checkout the async-profiler repository by input tag name ${{ inputs.async-profiler-tag-name }}
run: git checkout ${{ inputs.async-profiler-tag-name }}
# 安装 Liberica JDK 11
- uses: actions/setup-java@v3
with:
distribution: "liberica"
java-version: "11"
# 从 async-profiler 源码编译出 libasyncProfiler-mac.so(兼容 arthas-core 中 ProfilerCommand.java 固定的 so 文件名称未使用 libasyncProfiler.dylib)
# grep -m1 PROFILER_VERSION Makefile 用于输出 async-profiler 版本, 下同
- name: Execute compile inside macOS 12 environment
run: |
grep -m1 PROFILER_VERSION Makefile
echo "JAVA_HOME=${JAVA_HOME}"
java -version
echo "FAT_BINARY variable that make libasyncProfiler-mac.so works both on macOS x86-64 and arm64"
make FAT_BINARY=true
LIB_PROFILER_PATH=$(find build -type f \( -name libasyncProfiler.so -o -name libasyncProfiler.dylib \) 2>/dev/null)
[ -z "${LIB_PROFILER_PATH}" ] && echo "Can not find libasyncProfiler.so or libasyncProfiler.dylib file under build directory." && exit 1
echo "LIB_PROFILER_PATH=${LIB_PROFILER_PATH}"
file ${LIB_PROFILER_PATH}
otool -L ${LIB_PROFILER_PATH}
cp ${LIB_PROFILER_PATH} libasyncProfiler-mac.so
# 暂存编译出来的 libasyncProfiler-mac.so 文件
- uses: actions/upload-artifact@v3
with:
name: async-profiler
path: libasyncProfiler-mac.so
if-no-files-found: error
build-generic-linux-x64:
runs-on: ubuntu-20.04
if: ${{ inputs.async-profiler-tag-name }}
steps:
# 检出 async-profiler/async-profiler 项目指定的 tag
- uses: actions/checkout@v3
with:
repository: async-profiler/async-profiler
fetch-depth: 0
- name: Checkout the async-profiler repository by input tag name ${{ inputs.async-profiler-tag-name }}
run: git checkout ${{ inputs.async-profiler-tag-name }}
# 从 async-profiler 源码编译出适用于 glibc-based Linux 主机的 libasyncProfiler-linux-x64.so
- name: Execute compile inside CentOS 6 x86_64 docker container environment
uses: uraimo/run-on-arch-action@v2
with:
arch: none
distro: none
base_image: amd64/centos:6.10
run: |
cat /etc/system-release
uname -m
minorver=6.10
sed -e "s|^mirrorlist=|#mirrorlist=|g" \
-e "s|^#baseurl=http://mirror.centos.org/centos/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/$minorver|g" \
-i.bak /etc/yum.repos.d/CentOS-*.repo
yum -y update && yum install -y wget
wget --no-check-certificate https://people.centos.org/tru/devtools-1.1/devtools-1.1.repo -O /etc/yum.repos.d/devtools-1.1.repo
yum install -y devtoolset-1.1-gcc devtoolset-1.1-gcc-c++ devtoolset-1.1-binutils
export CC=/opt/centos/devtoolset-1.1/root/usr/bin/gcc
export CPP=/opt/centos/devtoolset-1.1/root/usr/bin/cpp
export CXX=/opt/centos/devtoolset-1.1/root/usr/bin/c++
ln -sf /opt/centos/devtoolset-1.1/root/usr/bin/* /usr/local/bin/
hash -r
wget https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz -O openjdk-11.tar.gz
tar zxf openjdk-11.tar.gz
mv jdk-11.0.2 /usr/local/
export JAVA_HOME=/usr/local/jdk-11.0.2
export PATH=${JAVA_HOME}/bin:${PATH}
java -version
which java
grep -m1 PROFILER_VERSION Makefile
make
LIB_PROFILER_PATH=$(find build -type f -name libasyncProfiler.so 2>/dev/null)
[ -z "${LIB_PROFILER_PATH}" ] && echo "Can not find libasyncProfiler.so file under build directory." && exit 1
echo "LIB_PROFILER_PATH=${LIB_PROFILER_PATH}"
file ${LIB_PROFILER_PATH}
ldd ${LIB_PROFILER_PATH}
cp ${LIB_PROFILER_PATH} libasyncProfiler-linux-x64.so
# 暂存编译出来的 libasyncProfiler-linux-x64.so 文件
- uses: actions/upload-artifact@v3
with:
name: async-profiler
path: libasyncProfiler-linux-x64.so
if-no-files-found: error
build-generic-linux-arm64:
runs-on: ubuntu-20.04
if: ${{ inputs.async-profiler-tag-name }}
steps:
# 检出 async-profiler/async-profiler 项目指定的 tag
- uses: actions/checkout@v3
with:
repository: async-profiler/async-profiler
fetch-depth: 0
- name: Checkout the async-profiler repository by input tag name ${{ inputs.async-profiler-tag-name }}
run: git checkout ${{ inputs.async-profiler-tag-name }}
# 从 async-profiler 源码编译出适用于 glibc-based Linux 主机的 libasyncProfiler-linux-arm64.so
- name: Execute compile inside CentOS 7 aarch64 docker container environment via QEMU
uses: uraimo/run-on-arch-action@v2
with:
arch: none
distro: none
base_image: arm64v8/centos:7
run: |
cat /etc/system-release
uname -m
yum -y update && yum install -y java-11-openjdk-devel gcc-c++ make which file
JAVA_HOME=/usr/lib/jvm/java-11-openjdk
java -version
which java
grep -m1 PROFILER_VERSION Makefile
make
LIB_PROFILER_PATH=$(find build -type f -name libasyncProfiler.so 2>/dev/null)
[ -z "${LIB_PROFILER_PATH}" ] && echo "Can not find libasyncProfiler.so file under build directory." && exit 1
echo "LIB_PROFILER_PATH=${LIB_PROFILER_PATH}"
file ${LIB_PROFILER_PATH}
ldd ${LIB_PROFILER_PATH}
cp ${LIB_PROFILER_PATH} libasyncProfiler-linux-arm64.so
# 暂存编译出来的 libasyncProfiler-linux-arm64.so 文件
- uses: actions/upload-artifact@v3
with:
name: async-profiler
path: libasyncProfiler-linux-arm64.so
if-no-files-found: error
build-alpine-linux-x64:
runs-on: ubuntu-20.04
if: ${{ inputs.async-profiler-tag-name }}
steps:
# 检出 async-profiler/async-profiler 项目指定的 tag
- uses: actions/checkout@v3
with:
repository: async-profiler/async-profiler
fetch-depth: 0
- name: Checkout the async-profiler repository by input tag name ${{ inputs.async-profiler-tag-name }}
run: git checkout ${{ inputs.async-profiler-tag-name }}
- name: Setup Alpine Linux x86-64 environment
uses: jirutka/setup-alpine@v1
with:
arch: x86_64
branch: v3.15
shell-name: alpine-x86_64.sh
packages: >
build-base linux-headers openjdk11
# 从 async-profiler 源码编译出适用于 musl-based Linux 主机的 libasyncProfiler-linux-musl-x64.so
# grep -m1 PROFILER_VERSION Makefile 用于输出 async-profiler 版本, 下同
- name: Run script inside Alpine Linux x86-64 environment
run: |
grep -m1 PROFILER_VERSION Makefile
JAVA_HOME=/usr/lib/jvm/java-11-openjdk
java -version
which java
echo "Append -static-libgcc -static-libstdc++ options to CXXFLAGS for user no need to install libstdc++ and libgcc manually."
sed -i 's/CXXFLAGS=/CXXFLAGS=-static-libgcc -static-libstdc++ /' Makefile && make
LIB_PROFILER_PATH=$(find build -type f -name libasyncProfiler.so 2>/dev/null)
[ -z "${LIB_PROFILER_PATH}" ] && echo "Can not find libasyncProfiler.so file under build directory." && exit 1
echo "LIB_PROFILER_PATH=${LIB_PROFILER_PATH}"
file ${LIB_PROFILER_PATH}
ldd ${LIB_PROFILER_PATH}
cp ${LIB_PROFILER_PATH} libasyncProfiler-linux-musl-x64.so
shell: alpine-x86_64.sh {0}
- uses: actions/upload-artifact@v3
with:
name: async-profiler
path: libasyncProfiler-linux-musl-x64.so
if-no-files-found: error
build-alpine-linux-arm64:
runs-on: ubuntu-20.04
if: ${{ inputs.async-profiler-tag-name }}
steps:
# 检出 async-profiler/async-profiler 项目指定的 tag
- uses: actions/checkout@v3
with:
repository: async-profiler/async-profiler
fetch-depth: 0
- name: Checkout the async-profiler repository by input tag name ${{ inputs.async-profiler-tag-name }}
run: git checkout ${{ inputs.async-profiler-tag-name }}
- name: Setup Alpine Linux aarch64 environment
uses: jirutka/setup-alpine@v1
with:
arch: aarch64
branch: v3.15
shell-name: alpine-aarch64.sh
packages: >
build-base linux-headers openjdk11
# 从 async-profiler 源码编译出适用于 musl-based Linux 主机的 libasyncProfiler-linux-musl-arm64.so
# grep -m1 PROFILER_VERSION Makefile 用于输出 async-profiler 版本, 下同
- name: Run script inside Alpine Linux aarch64 environment
run: |
grep -m1 PROFILER_VERSION Makefile
JAVA_HOME=/usr/lib/jvm/java-11-openjdk
java -version
which java
echo "Append -static-libgcc -static-libstdc++ options to CXXFLAGS for user no need to install libstdc++ and libgcc manually."
sed -i 's/CXXFLAGS=/CXXFLAGS=-static-libgcc -static-libstdc++ /' Makefile && make
LIB_PROFILER_PATH=$(find build -type f -name libasyncProfiler.so 2>/dev/null)
[ -z "${LIB_PROFILER_PATH}" ] && echo "Can not find libasyncProfiler.so file under build directory." && exit 1
echo "LIB_PROFILER_PATH=${LIB_PROFILER_PATH}"
file ${LIB_PROFILER_PATH}
ldd ${LIB_PROFILER_PATH}
cp ${LIB_PROFILER_PATH} libasyncProfiler-linux-musl-arm64.so
shell: alpine-aarch64.sh {0}
- uses: actions/upload-artifact@v3
with:
name: async-profiler
path: libasyncProfiler-linux-musl-arm64.so
if-no-files-found: error
upload-libasyncProfiler-files:
runs-on: ubuntu-20.04
needs: [build-mac, build-generic-linux-x64, build-generic-linux-arm64, build-alpine-linux-x64, build-alpine-linux-arm64]
steps:
# 检出当前 arthas 代码仓库
- name: Checkout arthas upstream repo
uses: actions/checkout@v3
# 将上面编译任务暂存的 libasyncProfiler 动态链接库文件上传到此工作流的 artifact 包中
- uses: actions/download-artifact@v3
with:
name: async-profiler
path: tmp-async-profiler
# 查看上面编译任务暂存的 libasyncProfiler 动态链接库文件
- name: Modify permissions and Display structure of downloaded files
run: |
chmod 755 libasyncProfiler-*
ls -lrt
working-directory: tmp-async-profiler
# 将编译好的 libasyncProfiler 动态链接库文件 push 到 arthas 代码仓库的 master 分支 async-profiler/ 目录下
- name: Commit and Push libasyncProfiler files
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
mv tmp-async-profiler/* async-profiler/
git add async-profiler/
git commit -m "Upload arthas async-profiler libs"
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
force: true

@ -1,55 +1,108 @@
name: build vmtool
on: [push]
on:
workflow_dispatch:
jobs:
linux:
runs-on: ubuntu-18.04
build-linux-x64:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up JDK 8
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'adopt'
- name: Build with Maven
run: ./mvnw package
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: lib
path: arthas-vmtool/target/lib*
mac:
runs-on: macos-10.15
path: arthas-vmtool/target/libArthasJniLibrary-x64.so
build-mac:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up JDK 8
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'adopt'
- name: Build with Maven
run: ./mvnw package
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: lib
path: arthas-vmtool/target/lib*
windows:
runs-on: windows-2016
path: arthas-vmtool/target/libArthas*
build-windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up JDK 8
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'adopt'
- name: Build with Maven
run: ./mvnw package
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: lib
path: arthas-vmtool/target/*.dll
build-linux-aarch64:
# The host should always be Linux
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- uses: uraimo/run-on-arch-action@v2
name: Run commands
id: runcmd
with:
arch: aarch64
distro: ubuntu20.04
# Not required, but speeds up builds by storing container images in
# a GitHub package registry.
githubToken: ${{ github.token }}
run: |
apt update && apt install openjdk-8-jdk g++ -y
./mvnw package -pl common,arthas-vmtool
cp arthas-vmtool/target/libArthas* lib/
- uses: actions/upload-artifact@v3
with:
name: lib
path: arthas-vmtool/target/libArthas*
commit_vmtool_files:
runs-on: ubuntu-20.04
needs: [build-linux-x64, build-linux-aarch64, build-mac, build-windows]
steps:
- name: Checkout Upstream Repo
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: lib
path: tmplib
- name: Display structure of downloaded files
run: ls -R
working-directory: tmplib
- name: Commit files
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
mv tmplib/* lib/
git add lib/
git commit -m "update arthas vmtool lib"
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}

@ -28,18 +28,18 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'java', 'javascript', 'python' ]
language: [ 'java', 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -50,7 +50,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -64,4 +64,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

@ -8,15 +8,13 @@ on:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
java-version: '8'
distribution: 'adopt'
- name: Build with Maven
run: mvn clean package -P full

@ -3,41 +3,50 @@ name: JavaCI
on: [push, pull_request]
jobs:
build:
ubuntu_build:
runs-on: ubuntu-latest
strategy:
matrix:
java: [7, 8, 9, 10, 11 ]
java: [8, 11, 17, 19]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: 'zulu'
cache: 'maven'
- name: Build with Maven
run: mvn clean package -P full
run: mvn clean install -P full
build_jdk_ge_12:
runs-on: ubuntu-latest
windows_build:
runs-on: windows-2019
strategy:
matrix:
java: [12, 13, 14 ]
java: [8, 11]
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v3
with:
java-version: 8
- name: save java8 home
run: |
export JAVA8_HOME=$JAVA_HOME && echo $JAVA8_HOME
echo "export JAVA8_HOME=$JAVA_HOME" > ~/.testenv
java-version: ${{ matrix.java }}
distribution: 'zulu'
cache: 'maven'
- name: Build with Maven
run: mvn clean install -P full
macos_build:
runs-on: macos-latest
strategy:
matrix:
java: [8, 11]
steps:
- uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: 'zulu'
cache: 'maven'
- name: Build with Maven
run: |
source ~/.testenv
mvn -Dmaven.compiler.fork=true -Dmaven.compiler.executable=$JAVA8_HOME/bin/javac -DJAVA8_HOME=$JAVA8_HOME clean package -P full
run: mvn clean install -P full

1
.gitignore vendored

@ -11,6 +11,7 @@
/nb-configuration.xml
**/target
core/src/main/resources/com/taobao/arthas/core/res/version
tunnel-server/src/main/resources/static
**/*.orig
site/src/site/sphinx/_build

@ -10,7 +10,7 @@ Welcome to use [issue tracker](https://github.com/alibaba/arthas/issues) to give
## Documentation
Welcome PR to further improve English [documentation](https://github.com/alibaba/arthas/tree/master/site/src/site/sphinx/en).
* Under `site/docs/`.
## Online Tutorials
@ -19,13 +19,18 @@ Please refer to [README.MD at tutorials/katacoda](tutorials/katacoda/README.md#c
## Developer
* Arthas runtime supports JDK6+
* To build Arthas requires JDK7+, because of the source code import JDK7 classes, such as `java.lang.management.BufferPoolMXBean`.
* It is recommended to use JDK8 to compile, and you will encounter problems when using a higher version. Reference https://github.com/alibaba/arthas/tree/master/.github/workflows
* If you encounter jfr related problems, it is recommended to use `8u262` and later versions of openjdk8 or zulu jdk8, https://mail.openjdk.org/pipermail/jdk8u-dev/2020-July/012143.html
### Local Installation
> Note: After modifying `arthas-vmtool` related codes, the packaging results need to be manually copied to the `lib/` path of this repo, and will not be copied automatically.
Recommend to use [`as-package.sh`](as-package.sh) to package, which will auto-install the latest Arthas to local `~/.arthas` and when debugging, Arthas will auto-load the latest version.
* To support jni, cpp compiling environment support is required
* mac needs to install xcode
* windows need to install gcc
F.Y.I
1. when using [`as.sh`](https://github.com/alibaba/arthas/blob/master/bin/as.sh) to start Arthas, it will get the latest version under `~/.arthas/lib`;
2. when [`as-package.sh`](as-package.sh) packaging, it will get the version from `pom.xml` and suffix it with the current timestamp e.g. `3.0.5.20180917161808`.
@ -52,16 +57,12 @@ Tip: you can use `--versions` to list all available versions.
### Packaging All
* Arthas is using [Sphinx](http://www.sphinx-doc.org/en/master/) to generate the static site
* `sphinx-maven-plugin` configured in [`site/pom.xml`](https://github.com/alibaba/arthas/tree/master/site)
* `sphinx-maven-plugin` executes by downloading`sphinx-binary/`
* when packaging the whole project (Packaging All), you need to execute:
```bash
./mvnw clean package -DskipTests -P full
```
---
@ -74,9 +75,7 @@ Tip: you can use `--versions` to list all available versions.
## 改进用户文档
用户文档在`site/src/site/sphinx`目录下如果希望改进arthas用户文档欢迎提交PR。
英文文档在`site/src/site/sphinx/en`目录下欢迎提交翻译PR。
用户文档在`site/docs/`目录下如果希望改进arthas用户文档欢迎提交PR。
## 改进在线教程
@ -85,12 +84,19 @@ Tip: you can use `--versions` to list all available versions.
## 开发者相关
* Arthas运行支持JDK6+
* 编译Arthas要求JDK7+因为使用到了jdk7里的`java.lang.management.BufferPoolMXBean`。
* 建议使用JDK8来编译使用高版本会遇到问题。参考 https://github.com/alibaba/arthas/tree/master/.github/workflows
* 如果遇到jfr相关问题建议使用`8u262`及之后的高版本 openjdk8 或者zulu jdk8 https://mail.openjdk.org/pipermail/jdk8u-dev/2020-July/012143.html
### 安装到本地
> 注意: 修改`arthas-vmtool`相关代码后,打包结果需要手动复制到本仓库的 `lib/` 路径下,不会自动复制。
本地开发时,推荐执行`as-package.sh`来打包会自动安装最新版本的arthas到`~/.arthas`目录里。debug时会自动使用最新版本。
* 代码里要编译jni需要cpp编译环境支持
* mac需要安装xcode
* windows需要安装gcc
`as.sh`在启动时,会对`~/.arthas/lib`下面的目录排序,取最新的版本。`as-package.sh`在打包时,会取`pom.xml`里的版本号,再拼接上当前时间,比如: `3.0.5.20180917161808`,这样子排序时取的就是最新的版本。
也可以直接 `./mvnw clean package -DskipTests`打包生成的zip在 `packaging/target/` 下面。但是注意`as.sh`启动加载的是`~/.arthas/lib`下面的版本。
@ -115,36 +121,22 @@ Tip: you can use `--versions` to list all available versions.
### 全量打包
* arthas是用sphinx来生成静态网站
* 在`site/pom.xml`里配置了`sphinx-maven-plugin`
* `sphinx-maven-plugin`通过下载`sphinx-binary/`来执行
* 全量打包时,需要配置下面的参数:
```
./mvnw clean package -DskipTests -P full
```
#### 当 sphinx-maven-plugin 下载出错时,可以用下面的方式
到 https://github.com/trustin/sphinx-binary/releases 下载对应版本的二进制文件,并在本地加上可执行权限。例如:
```
wget https://github.com/hengyunabc/sphinx-binary/releases/download/v0.4.0.1/sphinx.osx-x86_64 -o /tmp/sphinx.osx-x86_64
chmod +x /tmp/sphinx.osx-x86_64
./mvnw clean package -DskipTests -P full -Dsphinx.binUrl=file:/tmp/sphinx.osx-x86_64
```
### Release Steps
发布release版本流程
* 如果 arthas-vmtool 有更新则需要手动触发action构建后会把新的动态库文件提交到 lib 目录。 https://github.com/alibaba/arthas/actions/workflows/build-vmtool.yaml
* 修改`as.sh`里的版本,最后修改日期, `Bootstrap.java`里的版本Dockerfile里的版本
* 修改本地的maven settings.xml
* mvn clean deploy -DskipTests -P full -P release
如果在下载 sphinx-binary 出错,参考上面的 全量打包 的说明。
* 到 https://oss.sonatype.org/ 上“Staging Repositories”然后close掉自己的再release
* 发布后,可以到这里查看是否同步到仓库里了: https://repo1.maven.org/maven2/com/taobao/arthas/arthas-packaging/
* 发布完maven仓库之后需要到阿里云的仓库里检查是否同步有可能有延时
@ -157,16 +149,13 @@ chmod +x /tmp/sphinx.osx-x86_64
* 需要更新 gh-pages 分支下面的 arthas-boot.jar/math-game.jar/as.sh ,下载 doc.zip解压覆盖掉文档的更新
* 需要更新docker镜像push新的taghttps://hub.docker.com/r/hengyunabc/arthas/tags?page=1&ordering=last_updated
以 3.1.0 版本为例:
以 3.6.5 版本为例:
```
docker build . --build-arg ARTHAS_VERSION=3.1.0 -t hengyunabc/arthas:3.1.0
docker tag hengyunabc/arthas:3.1.0 hengyunabc/arthas:latest
docker push hengyunabc/arthas:3.1.0
docker push hengyunabc/arthas:latest
docker buildx build . --build-arg ARTHAS_VERSION=3.6.5 --build-arg MIRROR=true -t hengyunabc/arthas:3.6.5 -t hengyunabc/arthas:latest --platform=linux/arm64,linux/amd64 --push
docker build . --build-arg ARTHAS_VERSION=3.1.0 -f Dockerfile-No-Jdk -t hengyunabc/arthas:3.1.0-no-jdk
docker push hengyunabc/arthas:3.1.0-no-jdk
docker buildx build . --build-arg ARTHAS_VERSION=3.6.5 --build-arg MIRROR=true -f Dockerfile-No-Jdk -t hengyunabc/arthas:3.6.5-no-jdk --platform=linux/arm64,linux/amd64 --push
```
* 更新README.md比如增加了新命令要加上说明更新wiki的链接
* 更新release页面的 issue信息修改信息等
* 更新 https://arthas.aliyun.com/api/latest_version api
* 更新内部的版本

@ -1,6 +1,6 @@
FROM openjdk:8-jdk-alpine
ARG ARTHAS_VERSION="3.5.4"
ARG ARTHAS_VERSION="3.6.8"
ARG MIRROR=false
ENV MAVEN_HOST=https://repo1.maven.org/maven2 \

@ -1,6 +1,6 @@
FROM alpine
ARG ARTHAS_VERSION="3.5.4"
ARG ARTHAS_VERSION="3.6.8"
ARG MIRROR=false
ENV MAVEN_HOST=https://repo1.maven.org/maven2 \

@ -1,13 +1,14 @@
## Arthas
![arthas](site/src/site/sphinx/arthas.png)
![arthas](site/docs/.vuepress/public/images/arthas.png)
[![Build Status](https://travis-ci.org/alibaba/arthas.svg?branch=master)](https://travis-ci.org/alibaba/arthas)
[![Build Status](https://github.com/alibaba/arthas/workflows/JavaCI/badge.svg)](https://github.com/alibaba/arthas/actions)
[![codecov](https://codecov.io/gh/alibaba/arthas/branch/master/graph/badge.svg)](https://codecov.io/gh/alibaba/arthas)
[![maven](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg)](https://search.maven.org/search?q=g:com.taobao.arthas)
![license](https://img.shields.io/github/license/alibaba/arthas.svg)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Percentage of issues still open")
[![Leaderboard](https://img.shields.io/badge/Arthas-Check%20Your%20Contribution-orange)](https://opensource.alibaba.com/contribution_leaderboard/details?projectValue=arthas)
`Arthas` is a Java Diagnostic tool open sourced by Alibaba.
@ -101,7 +102,7 @@ You can enter its interactive interface by executing `as.sh`, or execute `as.sh
* https://arthas.aliyun.com/doc/en/dashboard
![dashboard](site/src/site/sphinx/_static/dashboard.png)
![dashboard](site/docs/.vuepress/public/images/dashboard.png)
#### Thread
@ -301,7 +302,7 @@ ts=2018-09-18 10:11:45;thread_name=http-bio-8080-exec-10;id=d9;is_daemon=true;pr
See what is slowing down your method invocation with trace command:
![trace](site/src/site/sphinx/_static/trace.png)
![trace](site/docs/.vuepress/public/images/trace.png)
#### Watch
@ -388,7 +389,7 @@ $ classloader
* https://arthas.aliyun.com/doc/en/web-console
![web console](site/src/site/sphinx/_static/web-console-local.png)
![web console](site/docs/.vuepress/public/images/web-console-local.png)
#### Profiler/FlameGraph
@ -402,13 +403,13 @@ Started [cpu] profiling
```
$ profiler stop
profiler output file: /tmp/demo/arthas-output/20191125-135546.svg
profiler output file: /tmp/demo/arthas-output/20211207-111550.html
OK
```
View profiler results under arthas-output via browser:
![](site/src/site/sphinx/_static/arthas-output-svg.jpg)
![](site/docs/.vuepress/public/images/arthas-output-svg.jpg)
#### Arthas Spring Boot Starter
@ -431,6 +432,8 @@ Welcome to register the company name in this issue: https://github.com/alibaba/a
![vipkid](static/vipkid.png)
![百度凤巢](static/baidufengchao.png)
![有赞](static/youzan.png)
![科大讯飞](static/iflytek.png)
![智联招聘](static/zhaopin.png)
### Derivative Projects

@ -2,15 +2,16 @@
## Arthas
![arthas](site/src/site/sphinx/arthas.png)
![arthas](site/docs/.vuepress/public/images/arthas.png)
[![Build Status](https://travis-ci.org/alibaba/arthas.svg?branch=master)](https://travis-ci.org/alibaba/arthas)
[![Build Status](https://github.com/alibaba/arthas/workflows/JavaCI/badge.svg)](https://github.com/alibaba/arthas/actions)
[![codecov](https://codecov.io/gh/alibaba/arthas/branch/master/graph/badge.svg)](https://codecov.io/gh/alibaba/arthas)
[![maven](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg)](https://search.maven.org/search?q=g:com.taobao.arthas)
![license](https://img.shields.io/github/license/alibaba/arthas.svg)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Percentage of issues still open")
English version goes [here](README.md).
`Arthas` 是Alibaba开源的Java诊断工具深受开发者喜爱。
@ -90,7 +91,7 @@ curl -L https://arthas.aliyun.com/install.sh | sh
* https://arthas.aliyun.com/doc/dashboard
![dashboard](site/src/site/sphinx/_static/dashboard.png)
![dashboard](site/docs/.vuepress/public/images/dashboard.png)
#### Thread
@ -286,7 +287,7 @@ ts=2018-09-18 10:11:45;thread_name=http-bio-8080-exec-10;id=d9;is_daemon=true;pr
观察方法执行的时候哪个子调用比较慢:
![trace](site/src/site/sphinx/_static/trace.png)
![trace](site/docs/.vuepress/public/images/trace.png)
#### Watch
@ -376,7 +377,7 @@ $ classloader
* https://arthas.aliyun.com/doc/web-console
![web console](site/src/site/sphinx/_static/web-console-local.png)
![web console](site/docs/.vuepress/public/images/web-console-local.png)
#### Profiler/FlameGraph/火焰图
@ -389,13 +390,13 @@ Started [cpu] profiling
```
$ profiler stop
profiler output file: /tmp/demo/arthas-output/20191125-135546.svg
profiler output file: /tmp/demo/arthas-output/20211207-111550.html
OK
```
通过浏览器查看profiler结果
![](site/src/site/sphinx/_static/arthas-output-svg.jpg)
![](site/docs/.vuepress/public/images/arthas-output-svg.jpg)
#### Arthas Spring Boot Starter
@ -418,6 +419,8 @@ Arthas有超过120家登记用户[查看全部](USERS.md)。
![vipkid](static/vipkid.png)
![百度凤巢](static/baidufengchao.png)
![有赞](static/youzan.png)
![科大讯飞](static/iflytek.png)
![智联招聘](static/zhaopin.png)
### 衍生项目

@ -128,6 +128,11 @@ Welcome to register the company name in this issue: https://github.com/alibaba/a
![有赞](static/youzan.png)
![中原银行](static/zhongyuanbank.png)
![CVTE](static/cvte.png)
![北京喜得国际网络科技有限公司](static/cider.png)
![智联招聘](static/zhaopin.png)
![深圳航天信息](static/ShenzhenAerospaceInformationCo.,Ltd.png)
![滴滴出行](static/didiglobal.jpg)
![兑观科技](static/videt.png)
* 网易云
* 派迩信息技术
@ -155,3 +160,4 @@ Welcome to register the company name in this issue: https://github.com/alibaba/a
* 车巴达
* 华为
* 云管书
* 兑观

@ -9,6 +9,7 @@
</parent>
<artifactId>arthas-agent</artifactId>
<name>arthas-agent</name>
<url>https://github.com/alibaba/arthas</url>
<dependencies>
<dependency>
@ -27,16 +28,6 @@
<build>
<finalName>arthas-agent</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>

@ -9,6 +9,7 @@
</parent>
<artifactId>arthas-agent-attach</artifactId>
<name>arthas-agent-attach</name>
<url>https://github.com/alibaba/arthas</url>
<dependencies>
<dependency>
@ -33,19 +34,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -13,6 +13,11 @@
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<url>https://github.com/alibaba/arthas</url>
<properties>
<it.pom.includes>*/pom.xml</it.pom.includes>
</properties>
<dependencyManagement>
<dependencies>
@ -63,6 +68,19 @@
</dependency>
</dependencies>
<profiles>
<profile>
<id>jdk-lt-17</id>
<activation>
<jdk>[1.8,17)</jdk>
</activation>
<properties>
<!-- spring boot3 测试只支持 jdk 17 及之后版本 -->
<it.pom.includes>arthas-spring-boot-starter-example/pom.xml</it.pom.includes>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
@ -78,6 +96,7 @@
<streamLogs>true</streamLogs>
<preBuildHookScript>setup</preBuildHookScript>
<postBuildHookScript>verify</postBuildHookScript>
<pomIncludes><pomInclude>${it.pom.includes}</pomInclude></pomIncludes>
</configuration>
<executions>
<execution>

@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<version>@spring-boot.version@</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>

@ -0,0 +1,5 @@
# A comma or space separated list of goals/phases to execute, may
# specify an empty list to execute the default goal of the IT project.
# Environment variables used by maven plugins can be added here
invoker.goals = clean spring-boot:run

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>@spring-boot3.version@</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>arthas-spring-boot3-starter-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>arthas-spring-boot3-starter-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,18 @@
package com.example.arthasspringboot3starterexample;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ArthasSpringBoot3StarterExampleApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(ArthasSpringBoot3StarterExampleApplication.class, args);
System.out.println("xxxxxxxxxxxxxxxxxx");
TimeUnit.SECONDS.sleep(3);
System.exit(0);
}
}

@ -0,0 +1,13 @@
package com.example.arthasspringbootstarterexample3;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ArthasSpringBoot3StarterExampleApplicationTests {
@Test
void contextLoads() {
}
}

@ -0,0 +1,3 @@
def file = new File(basedir, "build.log")
return file.text.contains("Arthas agent start success.")

@ -7,6 +7,7 @@ import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -36,7 +37,7 @@ public class ArthasConfiguration {
* </pre>
*/
@ConfigurationProperties(prefix = "arthas")
@ConditionalOnMissingBean
@ConditionalOnMissingBean(name="arthasConfigMap")
@Bean
public HashMap<String, String> arthasConfigMap() {
return new HashMap<String, String>();
@ -44,7 +45,7 @@ public class ArthasConfiguration {
@ConditionalOnMissingBean
@Bean
public ArthasAgent arthasAgent(@Autowired Map<String, String> arthasConfigMap,
public ArthasAgent arthasAgent(@Autowired @Qualifier("arthasConfigMap") Map<String, String> arthasConfigMap,
@Autowired ArthasProperties arthasProperties) throws Throwable {
arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap);
ArthasProperties.updateArthasConfigMapDefaultValue(arthasConfigMap);

@ -30,6 +30,9 @@ public class ArthasProperties {
*/
private long sessionTimeout;
private String username;
private String password;
private String home;
/**
@ -138,4 +141,20 @@ public class ArthasProperties {
public void setDisabledCommands(String disabledCommands) {
this.disabledCommands = disabledCommands;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

@ -12,7 +12,7 @@ import java.util.Map.Entry;
public class StringUtils {
public static Map<String, String> removeDashKey(Map<String, String> map) {
Map<String, String> result = new HashMap<String, String>();
Map<String, String> result = new HashMap<String, String>(map.size());
for (Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();

@ -0,0 +1,2 @@
com.alibaba.arthas.spring.ArthasConfiguration
com.alibaba.arthas.spring.endpoints.ArthasEndPointAutoConfiguration

@ -4,7 +4,7 @@ import java.util.HashMap;
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.jupiter.api.Test;
/**
*

@ -0,0 +1,2 @@
注意: 修改`arthas-vmtool`相关代码后,打包结果需要手动复制到本仓库的 `lib/` 路径下,不会自动复制。

@ -11,6 +11,7 @@
</parent>
<artifactId>arthas-vmtool</artifactId>
<name>arthas-vmtool</name>
<url>https://github.com/alibaba/arthas</url>
<profiles>
<!-- https://github.com/openjdk/jdk/blob/jdk-16%2B36/src/java.base/windows/native/libjava/java_props_md.c#L568 -->
@ -20,13 +21,12 @@
<activation>
<os>
<family>mac</family>
<arch>x86_64</arch>
</os>
</activation>
<properties>
<os_name>macos</os_name>
<os_arch_option>-m64</os_arch_option>
<lib_name>libArthasJniLibrary-x64.dylib</lib_name>
<os_name>darwin</os_name>
<os_arch_option>-arch x86_64 -arch arm64</os_arch_option>
<lib_name>libArthasJniLibrary.dylib</lib_name>
</properties>
</profile>
@ -45,8 +45,62 @@
<lib_name>libArthasJniLibrary-x64.so</lib_name>
</properties>
</profile>
<profile>
<id>linux-aarch64</id>
<activation>
<os>
<name>linux</name>
<arch>aarch64</arch>
</os>
</activation>
<properties>
<os_name>linux</os_name>
<os_arch_option>-march=armv8-a</os_arch_option>
<lib_name>libArthasJniLibrary-aarch64.so</lib_name>
</properties>
</profile>
<!-- linux other-arch-->
<profile>
<id>linux-${os.arch}</id>
<activation>
<os>
<name>linux</name>
<arch>!amd64</arch>
</os>
</activation>
<properties>
<os_name>linux</os_name>
<lib_name>libArthasJniLibrary-${os.arch}.so</lib_name>
</properties>
</profile>
<!-- windows -->
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<properties>
<!-- https://github.com/mojohaus/maven-native/blob/maven-native-1.0-alpha-11/native-maven-plugin/src/site/apt/examples/jni-dll.apt#L67-->
<os_name>win32</os_name>
</properties>
</profile>
<profile>
<id>windows-32</id>
<activation>
<os>
<family>windows</family>
<arch>x86</arch>
</os>
</activation>
<properties>
<os_arch_option>-m32</os_arch_option>
<lib_name>libArthasJniLibrary-x86.dll</lib_name>
</properties>
</profile>
<profile>
<id>windows-amd64</id>
<activation>
@ -56,12 +110,12 @@
</os>
</activation>
<properties>
<os_name>windows</os_name>
<os_arch_option>-m64</os_arch_option>
<lib_name>libArthasJniLibrary-x64.dll</lib_name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>native-maven-plugin</artifactId>
@ -73,7 +127,6 @@
<className>arthas.VmTool</className>
</javahInclude>
</javahIncludes>
<jdkIncludePath>${project.basedir}/src/main/native/head</jdkIncludePath>
<javahOS>${os_name}</javahOS>
<sources>
<source>
@ -87,6 +140,9 @@
<compilerProvider>generic-classic</compilerProvider>
<compilerExecutable>g++</compilerExecutable>
<compilerStartOptions>
<compilerStartOption>-I${JAVA_HOME}/include</compilerStartOption>
<compilerStartOption>-I${JAVA_HOME}/include/${os_name}</compilerStartOption>
<compilerStartOption>-I${project.build.directory}/native/include</compilerStartOption>
<compilerStartOption>${os_arch_option}</compilerStartOption>
<compilerStartOption>-fpic</compilerStartOption>
<compilerStartOption>-shared</compilerStartOption>
@ -110,10 +166,9 @@
</configuration>
<executions>
<execution>
<id>javah</id>
<id>compile-and-link</id>
<phase>compile</phase>
<goals>
<goal>javah</goal>
<goal>initialize</goal>
<goal>compile</goal>
<goal>link</goal>
@ -124,6 +179,7 @@
</plugins>
</build>
</profile>
</profiles>
<build>
@ -132,12 +188,14 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
<compilerArgs>
<!-- 需要使用 3.8.0 及之后版本使用javac -h 生成头文件 -->
<arg>-h</arg>
<arg>${project.build.directory}/native/include</arg>
</compilerArgs>
</configuration>
</plugin>
<!-- 请不要删除这里的maven-jar-plugin也不要升级它的版本否则很可能无法正常打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -155,8 +213,6 @@
<className>arthas.VmTool</className>
</javahInclude>
</javahIncludes>
<jdkIncludePath>${project.basedir}/src/main/native/head</jdkIncludePath>
<javahOS>${os_name}</javahOS>
<sources>
<source>
<directory>src/main/native/src</directory>
@ -169,6 +225,9 @@
<compilerProvider>generic-classic</compilerProvider>
<compilerExecutable>g++</compilerExecutable>
<compilerStartOptions>
<compilerStartOption>-I${JAVA_HOME}/include</compilerStartOption>
<compilerStartOption>-I${JAVA_HOME}/include/${os_name}</compilerStartOption>
<compilerStartOption>-I${project.build.directory}/native/include</compilerStartOption>
<compilerStartOption>${os_arch_option}</compilerStartOption>
<compilerStartOption>-fpic</compilerStartOption>
<compilerStartOption>-shared</compilerStartOption>
@ -181,7 +240,7 @@
<linkerStartOption>${os_arch_option}</linkerStartOption>
<linkerStartOption>-fpic</linkerStartOption>
<linkerStartOption>-shared</linkerStartOption>
<linkerStartOption>-o</linkerStartOption>
<!-- <linkerStartOption>-o</linkerStartOption> -->
</linkerStartOptions>
<linkerEndOptions>
<linkerEndOption>-o ${project.build.directory}/${lib_name}</linkerEndOption>
@ -189,10 +248,9 @@
</configuration>
<executions>
<execution>
<id>javah</id>
<id>compile-and-link</id>
<phase>compile</phase>
<goals>
<goal>javah</goal>
<goal>initialize</goal>
<goal>compile</goal>
<goal>link</goal>

@ -1,5 +1,7 @@
package arthas;
import java.util.Map;
/**
* @author ZhangZiCheng 2021-02-12
* @author hengyunabc 2021-04-26
@ -70,6 +72,17 @@ public class VmTool implements VmToolMXBean {
forceGc0();
}
@Override
public void interruptSpecialThread(int threadId) {
Map<Thread, StackTraceElement[]> allThread = Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> entry : allThread.entrySet()) {
if (entry.getKey().getId() == threadId) {
entry.getKey().interrupt();
return;
}
}
}
@Override
public <T> T[] getInstances(Class<T> klass) {
return getInstances0(klass, -1);

@ -20,6 +20,13 @@ public interface VmToolMXBean {
*/
public void forceGc();
/**
* 线
*
* @param threadId 线ID
*/
void interruptSpecialThread(int threadId);
public <T> T[] getInstances(Class<T> klass);
/**

@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 3.17)
project(arthas-native)
set(CMAKE_CXX_STANDARD 14)
add_library(jni-lib SHARED src/jni-library.cpp)
#使includejdk
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 ()

@ -1,588 +0,0 @@
/*
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef CLASSFILE_CONSTANTS_H
#define CLASSFILE_CONSTANTS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Classfile version number for this information */
#define JVM_CLASSFILE_MAJOR_VERSION 60
#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,
JVM_ACC_MODULE = 0x8000
};
#define JVM_ACC_PUBLIC_BIT 0
#define JVM_ACC_PRIVATE_BIT 1
#define JVM_ACC_PROTECTED_BIT 2
#define JVM_ACC_STATIC_BIT 3
#define JVM_ACC_FINAL_BIT 4
#define JVM_ACC_SYNCHRONIZED_BIT 5
#define JVM_ACC_SUPER_BIT 5
#define JVM_ACC_VOLATILE_BIT 6
#define JVM_ACC_BRIDGE_BIT 6
#define JVM_ACC_TRANSIENT_BIT 7
#define JVM_ACC_VARARGS_BIT 7
#define JVM_ACC_NATIVE_BIT 8
#define JVM_ACC_INTERFACE_BIT 9
#define JVM_ACC_ABSTRACT_BIT 10
#define JVM_ACC_STRICT_BIT 11
#define JVM_ACC_SYNTHETIC_BIT 12
#define JVM_ACC_ANNOTATION_BIT 13
#define JVM_ACC_ENUM_BIT 14
/* 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_Dynamic = 17,
JVM_CONSTANT_InvokeDynamic = 18,
JVM_CONSTANT_Module = 19,
JVM_CONSTANT_Package = 20,
JVM_CONSTANT_ExternalMax = 20
};
/* 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_SLASH = '/',
JVM_SIGNATURE_DOT = '.',
JVM_SIGNATURE_SPECIAL = '<',
JVM_SIGNATURE_ENDSPECIAL = '>',
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 */

@ -1,356 +0,0 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JAWT_H_
#define _JAVASOFT_JAWT_H_
#include "jni.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* AWT native interface.
*
* 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
* developers who need to do their own native rendering to canvases
* for performance or other reasons.
*
* Conversely it also provides mechanisms for an application which already
* has a native window to provide that to AWT for AWT rendering.
*
* Since every platform may be different in its native data structures
* and APIs for windowing systems the application must necessarily
* provided per-platform source and compile and deliver per-platform
* native code to use this API.
*
* These interfaces are not part of the Java SE specification and
* a VM is not required to implement this API. However it is strongly
* recommended that all implementations which support headful AWT
* also support these interfaces.
*
*/
/*
* 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 all platforms 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 <assert.h>
*
* 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. Request version 9 to access features in that release.
* awt.version = JAWT_VERSION_9;
* 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 Linux and 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(). It affects the functions returned.
* Must be one of the known pre-defined versions.
*/
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);
/**
* Since 9
* Creates a java.awt.Frame placed in a native container. Container is
* referenced by the native platform handle. For example on Windows this
* corresponds to an HWND. 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 frame could be
* created with matching platform information.
*/
jobject (JNICALL *CreateEmbeddedFrame) (JNIEnv *env, void* platformInfo);
/**
* Since 9
* Moves and resizes the embedded frame. The new location of the top-left
* corner is specified by x and y parameters relative to the native parent
* component. The new size is specified by width and height.
*
* The embedded frame should be created by CreateEmbeddedFrame() method, or
* this function will not have any effect.
*
* java.awt.Component.setLocation() and java.awt.Component.setBounds() for
* EmbeddedFrame really don't move it within the native parent. These
* methods always locate the embedded frame at (0, 0) for backward
* compatibility. To allow moving embedded frames this method was
* introduced, and it works just the same way as setLocation() and
* setBounds() for usual, non-embedded components.
*
* Using usual get/setLocation() and get/setBounds() together with this new
* method is not recommended.
*/
void (JNICALL *SetBounds) (JNIEnv *env, jobject embeddedFrame,
jint x, jint y, jint w, jint h);
/**
* Since 9
* Synthesize a native message to activate or deactivate an EmbeddedFrame
* window depending on the value of parameter doActivate, if "true"
* activates the window; otherwise, deactivates the window.
*
* The embedded frame should be created by CreateEmbeddedFrame() method, or
* this function will not have any effect.
*/
void (JNICALL *SynthesizeWindowActivation) (JNIEnv *env,
jobject embeddedFrame, jboolean doActivate);
} 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);
/*
* Specify one of these constants as the JAWT.version
* Specifying an earlier version will limit the available functions to
* those provided in that earlier version of JAWT.
* See the "Since" note on each API. Methods with no "Since"
* may be presumed to be present in JAWT_VERSION_1_3.
*/
#define JAWT_VERSION_1_3 0x00010003
#define JAWT_VERSION_1_4 0x00010004
#define JAWT_VERSION_1_7 0x00010007
#define JAWT_VERSION_9 0x00090000
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !_JAVASOFT_JAWT_H_ */

@ -1,276 +0,0 @@
/*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Java Debug Wire Protocol Transport Service Provider Interface.
*/
#ifndef JDWPTRANSPORT_H
#define JDWPTRANSPORT_H
#include "jni.h"
enum {
JDWPTRANSPORT_VERSION_1_0 = 0x00010000,
JDWPTRANSPORT_VERSION_1_1 = 0x00010001
};
#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
*/
#define JDWP_HEADER_SIZE 11
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);
/*
* JDWP transport configuration from the agent.
*/
typedef struct jdwpTransportConfiguration {
/* Field added in JDWPTRANSPORT_VERSION_1_1: */
const char* allowed_peers; /* Peers allowed for connection */
} jdwpTransportConfiguration;
/* 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);
/* 12: SetTransportConfiguration added in JDWPTRANSPORT_VERSION_1_1 */
jdwpTransportError (JNICALL *SetTransportConfiguration)(jdwpTransportEnv* env,
jdwpTransportConfiguration *config);
};
/*
* 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);
}
/* SetTransportConfiguration added in JDWPTRANSPORT_VERSION_1_1 */
jdwpTransportError SetTransportConfiguration(jdwpTransportEnv* env,
return functions->SetTransportConfiguration(this, config);
}
#endif /* __cplusplus */
};
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* JDWPTRANSPORT_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,115 +0,0 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* 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

@ -1,60 +0,0 @@
/*
* Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#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_ */

@ -1,66 +0,0 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef JNIEXPORT
#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
#ifdef ARM
#define JNIEXPORT __attribute__((externally_visible,visibility("default")))
#else
#define JNIEXPORT __attribute__((visibility("default")))
#endif
#else
#define JNIEXPORT
#endif
#endif
#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
#ifdef ARM
#define JNIIMPORT __attribute__((externally_visible,visibility("default")))
#else
#define JNIIMPORT __attribute__((visibility("default")))
#endif
#else
#define JNIIMPORT
#endif
#define JNICALL
typedef int jint;
#ifdef _LP64
typedef long jlong;
#else
typedef long long jlong;
#endif
typedef signed char jbyte;
#endif /* !_JAVASOFT_JNI_MD_H_ */

@ -1,77 +0,0 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include "jawt.h"
#ifdef __OBJC__
#import <QuartzCore/CALayer.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* MacOS 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_ */

@ -1,42 +0,0 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#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_ */

@ -1,92 +0,0 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Header file defining callback typedefs for Windows routines
* which are called from Java (responding to events, etc.).
*/
#ifndef __AccessBridgeCallbacks_H__
#define __AccessBridgeCallbacks_H__
#include <jni.h>
#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

@ -1,725 +0,0 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* Note: In addition to this header file AccessBridgeCalls.c must be compiled and
* linked to your application. AccessBridgeCalls.c implements the Java Access
* Bridge API and also hides the complexities associated with interfacing to the
* associated Java Access Bridge DLL which is installed when Java is installed.
*
* AccessBridgeCalls.c is available for download from the OpenJDK repository using
* the following link:
*
* http://hg.openjdk.java.net/jdk9/jdk9/jdk/raw-file/tip/src/jdk.accessibility/windows/native/bridge/AccessBridgeCalls.c
*
* Also note that the API is used in the jaccessinspector and jaccesswalker tools.
* The source for those tools is available in the OpenJDK repository at these links:
*
* http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/tip/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspector.cpp
* http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/tip/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp
*
*
*/
/*
* Wrapper functions around calls to the AccessBridge DLL
*/
#include <windows.h>
#include <jni.h>
#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

@ -1,59 +0,0 @@
/*
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include <windows.h>
#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_ */

@ -1,40 +0,0 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#ifndef JNIEXPORT
#define JNIEXPORT __declspec(dllexport)
#endif
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall
// 'long' is always 32 bit on windows so this matches what jdk expects
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
#endif /* !_JAVASOFT_JNI_MD_H_ */

@ -1,4 +1,4 @@
#include <iostream>
#include <stdio.h>
#include <jni.h>
#include <jni_md.h>
#include <jvmti.h>

@ -3,9 +3,11 @@ package arthas;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Test;
import com.taobao.arthas.common.VmToolUtils;
@ -182,4 +184,30 @@ public class VmToolTest {
Assertions.assertThat(interfaceInstances[0]).isEqualTo(ObjectInstances[0]);
}
@Test
public void test_interrupt_thread() throws InterruptedException {
String threadName = "interruptMe";
final RuntimeException[] re = new RuntimeException[1];
Runnable runnable = new Runnable() {
@Override public void run() {
try {
System.out.printf("Thread name is: [%s], thread id is: [%d].\n", Thread.currentThread().getName(),Thread.currentThread().getId());
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
re[0] = new RuntimeException("interrupted " + Thread.currentThread().getId() + " thread success.");
}
}
};
Thread interruptMe = new Thread(runnable,threadName);
Thread interruptMe1 = new Thread(runnable,threadName);
interruptMe.start();
interruptMe1.start();
VmTool tool = initVmTool();
tool.interruptSpecialThread((int) interruptMe.getId());
TimeUnit.SECONDS.sleep(5);
Assert.assertEquals(("interrupted " + interruptMe.getId() + " thread success."), re[0].getMessage());
}
}

@ -115,5 +115,5 @@ IF %ERRORLEVEL% NEQ 0 (
)
:exit_bat
if %exitProcess%==1 exit %ERROR_CODE%
if "%exitProcess%"=="1" exit %ERROR_CODE%
exit /B %ERROR_CODE%

@ -8,10 +8,10 @@
# program : Arthas
# author : Core Engine @ Taobao.com
# date : 2021-09-02
# date : 2023-04-19
# current arthas script version
ARTHAS_SCRIPT_VERSION=3.5.4
ARTHAS_SCRIPT_VERSION=3.6.8
# SYNOPSIS
# rreadlink <fileOrDirPath>
@ -85,6 +85,8 @@ ARTHAS_HOME=
# define arthas's lib
if [ -z "${ARTHAS_LIB_DIR}" ]; then
ARTHAS_LIB_DIR=${HOME}/.arthas/lib
else
echo "[INFO] ARTHAS_LIB_DIR: ${ARTHAS_LIB_DIR}"
fi
# target process id to attach
@ -184,7 +186,7 @@ case "$(uname -s)" in
*) OS_TYPE="UNKNOWN"
esac
# check curl/grep/awk/telent/unzip command
# check curl/grep/awk/telnet/unzip command
if ! [ -x "$(command -v curl)" ]; then
echo 'Error: curl is not installed. Try to use java -jar arthas-boot.jar' >&2
exit 1
@ -391,12 +393,32 @@ update_if_necessary()
fi
}
# jps command may crash, so need to check it
check_jps() {
"${JAVA_HOME}/bin/jps" > /dev/null 2>&1
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "jps command failed with exit code ${exit_code}" >&2
fi
return $exit_code
}
call_jps()
{
check_jps
local exit_code=$?
if [[ "$exit_code" -eq 0 ]]; then
# jps command is ok
local jps_command=("${JAVA_HOME}/bin/jps" "-l")
if [ "${VERBOSE}" = true ] ; then
"${JAVA_HOME}"/bin/jps -l -v
jps_command=("${JAVA_HOME}/bin/jps" "-l" "-v")
fi
local jps_output=$("${jps_command[@]}")
echo "$jps_output"
else
"${JAVA_HOME}"/bin/jps -l
# jps command failed, use ps and grep
ps_output=$(ps aux | grep java | grep -v grep | awk '{print $2" "$11}')
echo "$ps_output"
fi
}
@ -453,7 +475,7 @@ EXAMPLES:
./as.sh --stat-url 'http://192.168.10.11:8080/api/stat'
./as.sh -c 'sysprop; thread' <pid>
./as.sh -f batch.as <pid>
./as.sh --use-version 3.5.4
./as.sh --use-version 3.6.8
./as.sh --session-timeout 3600
./as.sh --attach-only
./as.sh --disabled-commands stop,dump

@ -9,6 +9,7 @@
</parent>
<artifactId>arthas-boot</artifactId>
<name>arthas-boot</name>
<url>https://github.com/alibaba/arthas</url>
<dependencies>
<dependency>
@ -30,16 +31,6 @@
<build>
<finalName>arthas-boot</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>

@ -53,7 +53,7 @@ import com.taobao.middleware.cli.annotations.Summary;
+ " java -jar arthas-boot.jar --stat-url 'http://192.168.10.11:8080/api/stat'\n"
+ " java -jar arthas-boot.jar -c 'sysprop; thread' <pid>\n"
+ " java -jar arthas-boot.jar -f batch.as <pid>\n"
+ " java -jar arthas-boot.jar --use-version 3.5.4\n"
+ " java -jar arthas-boot.jar --use-version 3.6.8\n"
+ " java -jar arthas-boot.jar --versions\n"
+ " java -jar arthas-boot.jar --select math-game\n"
+ " java -jar arthas-boot.jar --session-timeout 3600\n" + " java -jar arthas-boot.jar --attach-only\n"
@ -135,6 +135,7 @@ public class Bootstrap {
String arthasLibDirEnv = System.getenv("ARTHAS_LIB_DIR");
if (arthasLibDirEnv != null) {
ARTHAS_LIB_DIR = new File(arthasLibDirEnv);
AnsiLog.info("ARTHAS_LIB_DIR: " + arthasLibDirEnv);
} else {
ARTHAS_LIB_DIR = new File(
System.getProperty("user.home") + File.separator + ".arthas" + File.separator + "lib");
@ -311,6 +312,10 @@ public class Bootstrap {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException,
ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
String javaHome = System.getProperty("java.home");
if (javaHome != null) {
AnsiLog.info("JAVA_HOME: " + javaHome);
}
Package bootstrapPackage = Bootstrap.class.getPackage();
if (bootstrapPackage != null) {
String arthasBootVersion = bootstrapPackage.getImplementationVersion();
@ -319,6 +324,15 @@ public class Bootstrap {
}
}
try {
String javaToolOptions = System.getenv("JAVA_TOOL_OPTIONS");
if (javaToolOptions != null && !javaToolOptions.trim().isEmpty()) {
AnsiLog.info("JAVA_TOOL_OPTIONS: " + javaToolOptions);
}
} catch (Throwable e) {
// ignore
}
Bootstrap bootstrap = new Bootstrap();
CLI cli = CLIConfigurator.define(Bootstrap.class);
@ -398,7 +412,7 @@ public class Bootstrap {
pid, bootstrap.getHttpPortOrDefault());
AnsiLog.error("1. Try to restart arthas-boot, select process {}, shutdown it first with running the 'stop' command.",
httpPortPid);
AnsiLog.error("2. Or try to use different http port, for example: java -jar arthas-boot.jar --telnet-port 9998 --http-port 9999", httpPortPid);
AnsiLog.error("2. Or try to use different http port, for example: java -jar arthas-boot.jar --telnet-port 9998 --http-port 9999");
System.exit(1);
}
@ -504,6 +518,9 @@ public class Bootstrap {
//double check telnet port and pid before attach
telnetPortPid = findProcessByTelnetClient(arthasHomeDir.getAbsolutePath(), bootstrap.getTelnetPortOrDefault());
checkTelnetPortPid(bootstrap, telnetPortPid, pid);
if (telnetPortPid > 0 && pid == telnetPortPid) {
AnsiLog.info("The target process already listen port {}, skip attach.", bootstrap.getTelnetPortOrDefault());
} else {
// start arthas-core.jar
List<String> attachArgs = new ArrayList<String>();
@ -562,7 +579,7 @@ public class Bootstrap {
attachArgs.add(bootstrap.getStatUrl());
}
if (bootstrap.getDisabledCommands() != null){
if (bootstrap.getDisabledCommands() != null) {
attachArgs.add("-disabled-commands");
attachArgs.add(bootstrap.getDisabledCommands());
}
@ -573,6 +590,7 @@ public class Bootstrap {
AnsiLog.info("Attach process {} success.", pid);
}
}
if (bootstrap.isAttachOnly()) {
System.exit(0);
@ -699,9 +717,13 @@ public class Bootstrap {
result.append("Remote versions:\n");
List<String> remoteVersions = DownloadUtils.readRemoteVersions();
if (remoteVersions != null) {
Collections.reverse(remoteVersions);
for (String version : remoteVersions) {
result.append(" ").append(version).append('\n');
result.append(" " + version).append('\n');
}
} else {
result.append(" unknown\n");
}
return result.toString();
}

@ -118,7 +118,7 @@ public class DownloadUtils {
int totalCount = 0;
int count;
long lastPrintTime = System.currentTimeMillis();
while ((count = in.read(data, 0, 1024 * 1024)) != -1) {
while ((count = in.read(data, 0, data.length)) != -1) {
totalCount += count;
if (printProgress) {
long now = System.currentTimeMillis();

@ -129,7 +129,7 @@ public class ProcessUtils {
jps = jpsFile.getAbsolutePath();
}
AnsiLog.debug("Try use jps to lis java process, jps: " + jps);
AnsiLog.debug("Try use jps to list java process, jps: " + jps);
String[] command = null;
if (v) {
@ -266,6 +266,8 @@ public class ProcessUtils {
// -agent "${arthas_lib_dir}/arthas-agent.jar"
ProcessBuilder pb = new ProcessBuilder(command);
// https://github.com/alibaba/arthas/issues/2166
pb.environment().put("JAVA_TOOL_OPTIONS", "");
try {
final Process proc = pb.start();
Thread redirectStdout = new Thread(new Runnable() {

@ -10,20 +10,11 @@
<artifactId>arthas-client</artifactId>
<name>arthas-client</name>
<url>https://github.com/alibaba/arthas</url>
<build>
<finalName>arthas-client</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>

@ -215,7 +215,7 @@ public class TelnetConsole {
if (telnetConsole.isHelp()) {
System.out.println(usage(cli));
return STATUS_ERROR;
return STATUS_OK;
}
// Try to read cmds

@ -1065,7 +1065,7 @@ class Telnet extends SocketClient
_output_.flush();
}
aytMonitor.wait(timeout);
if (aytFlag == false)
if (!aytFlag)
{
retValue = false;
aytFlag = true;

@ -9,22 +9,11 @@
</parent>
<artifactId>arthas-common</artifactId>
<name>arthas-common</name>
<url>https://github.com/alibaba/arthas</url>
<!-- This module can not add any dependencies -->
<build>
<finalName>arthas-common</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -278,7 +278,7 @@ public abstract class AnsiLog {
String computed = from;
if (arguments != null && arguments.length != 0) {
for (Object argument : arguments) {
computed = computed.replaceFirst("\\{\\}", Matcher.quoteReplacement(argument.toString()));
computed = computed.replaceFirst("\\{\\}", Matcher.quoteReplacement(String.valueOf(argument)));
}
}
return computed;

@ -14,7 +14,7 @@ public class ArthasConstants {
*/
public static final String NETTY_LOCAL_ADDRESS = "arthas-netty-LocalAddress";
public static final int MAX_HTTP_CONTENT_LENGTH = 1024 * 1024 * 8;
public static final int MAX_HTTP_CONTENT_LENGTH = 1024 * 1024 * 10;
public static final String ARTHAS_OUTPUT = "arthas-output";
@ -26,7 +26,7 @@ public class ArthasConstants {
public static final int TELNET_PORT = 3658;
public static final String DEFAULT_WEBSOCKET_PATH = "/ws";
public static final int WEBSOCKET_IDLE_SECONDS = 60;
public static final int WEBSOCKET_IDLE_SECONDS = 10;
/**
* HTTP cookie id

@ -115,7 +115,7 @@ public class FileUtils {
if (file.isDirectory()) {
throw new IOException("File '" + file + "' exists but is a directory");
}
if (file.canWrite() == false) {
if (!file.canWrite()) {
throw new IOException("File '" + file + "' cannot be written to");
}
} else {

@ -1,5 +1,6 @@
package com.taobao.arthas.common;
import java.io.File;
import java.util.Locale;
/**
@ -67,6 +68,14 @@ public class OSUtils {
return "aarch_64".equals(arch);
}
public static boolean isX86() {
return "x86_32".equals(arch);
}
public static boolean isX86_64() {
return "x86_64".equals(arch);
}
private static String normalizeArch(String value) {
value = normalize(value);
if (value.matches("^(x8664|amd64|ia32e|em64t|x64)$")) {
@ -123,8 +132,18 @@ public class OSUtils {
if ("s390x".equals(value)) {
return "s390_64";
}
return value;
}
return UNKNOWN;
public static boolean isMuslLibc() {
File ld_musl_x86_64_file = new File("/lib/ld-musl-x86_64.so.1");
File ld_musl_aarch64_file = new File("/lib/ld-musl-aarch64.so.1");
if(ld_musl_x86_64_file.exists() || ld_musl_aarch64_file.exists()){
return true;
}
return false;
}
private static String normalize(String value) {

@ -9,18 +9,24 @@ public class VmToolUtils {
private static String libName = null;
static {
if (OSUtils.isMac()) {
libName = "libArthasJniLibrary-x64.dylib";
libName = "libArthasJniLibrary.dylib";
}
if (OSUtils.isLinux()) {
libName = "libArthasJniLibrary-x64.so";
if (OSUtils.isArm32()) {
libName = "libArthasJniLibrary-arm.so";
} else if (OSUtils.isArm64()) {
libName = "libArthasJniLibrary-aarch64.so";
} else if (OSUtils.isX86_64()) {
libName = "libArthasJniLibrary-x64.so";
}else {
libName = "libArthasJniLibrary-" + OSUtils.arch() + ".so";
}
}
if (OSUtils.isWindows()) {
libName = "libArthasJniLibrary-x64.dll";
if (OSUtils.isX86()) {
libName = "libArthasJniLibrary-x86.dll";
}
}
}

@ -9,6 +9,7 @@
</parent>
<artifactId>arthas-core</artifactId>
<name>arthas-core</name>
<url>https://github.com/alibaba/arthas</url>
<properties>
<arthas.deps.package>com.alibaba.arthas.deps</arthas.deps.package>
@ -17,17 +18,6 @@
<build>
<finalName>arthas-core</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@ -66,6 +56,10 @@
<pattern>io.netty</pattern>
<shadedPattern>${arthas.deps.package}.io.netty</shadedPattern>
</relocation>
<relocation>
<pattern>com.alibaba.fastjson2</pattern>
<shadedPattern>${arthas.deps.package}.com.alibaba.fastjson2</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@ -95,6 +89,10 @@
<copy overwrite="true" todir="${project.build.directory}/tmp_out/com/taobao/arthas/core/command/logger">
<fileset dir="${project.build.directory}/classes/com/taobao/arthas/core/command/logger" />
</copy>
<!-- 从web-ui复制打包好的js/html -->
<copy overwrite="true" todir="${project.build.directory}/tmp_out/com/taobao/arthas/core/http/">
<fileset dir="${project.build.directory}/../../web-ui/arthasWebConsole/dist/ui/" />
</copy>
<zip basedir="${project.build.directory}/tmp_out" destfile="${project.build.directory}/${project.build.finalName}-shade.${project.packaging}" />
</tasks>
</configuration>
@ -201,13 +199,13 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
<version>2.12.4</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<dependency>
<groupId>ognl</groupId>
@ -260,7 +258,6 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

@ -12,6 +12,7 @@ import com.taobao.middleware.cli.CommandLine;
import com.taobao.middleware.cli.Option;
import com.taobao.middleware.cli.TypedOption;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
@ -117,8 +118,29 @@ public class Arthas {
//convert jar path to unicode string
configure.setArthasAgent(encodeArg(arthasAgentPath));
configure.setArthasCore(encodeArg(configure.getArthasCore()));
try {
virtualMachine.loadAgent(arthasAgentPath,
configure.getArthasCore() + ";" + configure.toString());
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("Non-numeric value found")) {
AnsiLog.warn(e);
AnsiLog.warn("It seems to use the lower version of JDK to attach the higher version of JDK.");
AnsiLog.warn(
"This error message can be ignored, the attach may have been successful, and it will still try to connect.");
} else {
throw e;
}
} catch (com.sun.tools.attach.AgentLoadException ex) {
if ("0".equals(ex.getMessage())) {
// https://stackoverflow.com/a/54454418
AnsiLog.warn(ex);
AnsiLog.warn("It seems to use the higher version of JDK to attach the lower version of JDK.");
AnsiLog.warn(
"This error message can be ignored, the attach may have been successful, and it will still try to connect.");
} else {
throw ex;
}
}
} finally {
if (null != virtualMachine) {
virtualMachine.detach();

@ -7,6 +7,9 @@ import com.taobao.arthas.common.JavaVersionUtils;
* Created by vlinux on 15/6/4.
*/
public class GlobalOptions {
public static final String STRICT_MESSAGE = "By default, strict mode is true, "
+ "not allowed to set object properties. "
+ "Want to set object properties, execute `options strict false`";
/**
* <br/>
@ -79,7 +82,7 @@ public class GlobalOptions {
summary = "Option to control include default method in interface when class matching",
description = "This option disable to include default method in interface when matching class."
)
public static volatile boolean isSupportDefaultMethod = true && JavaVersionUtils.isGreaterThanJava7();
public static volatile boolean isSupportDefaultMethod = JavaVersionUtils.isGreaterThanJava7();
/**
*
@ -123,4 +126,14 @@ public class GlobalOptions {
description = "This option enables print verbose information, default value false."
)
public static volatile boolean verbose = false;
/**
* strict
*/
@Option(level = 1,
name = "strict",
summary = "Option to strict mode",
description = STRICT_MESSAGE
)
public static volatile boolean strict = true;
}

@ -106,7 +106,7 @@ public class Advice {
);
}
public static Advice newForAfterRetuning(ClassLoader loader,
public static Advice newForAfterReturning(ClassLoader loader,
Class<?> clazz,
ArthasMethod method,
Object target,

@ -23,8 +23,7 @@ public interface AdviceListener {
/**
*
*
* @param loader
* @param className
* @param clazz
* @param methodName
* @param methodDesc
* @param target
@ -39,8 +38,7 @@ public interface AdviceListener {
/**
*
*
* @param loader
* @param className
* @param clazz
* @param methodName
* @param methodDesc
* @param target
@ -58,8 +56,7 @@ public interface AdviceListener {
/**
*
*
* @param loader
* @param className
* @param clazz
* @param methodName
* @param methodDesc
* @param target

@ -60,7 +60,6 @@ public class AdviceListenerManager {
@Override
public void run() {
try {
if (adviceListenerMap != null) {
for (Entry<ClassLoader, ClassLoaderAdviceListenerManager> entry : adviceListenerMap.entrySet()) {
ClassLoaderAdviceListenerManager adviceListenerManager = entry.getValue();
synchronized (adviceListenerManager) {
@ -88,7 +87,6 @@ public class AdviceListenerManager {
}
}
}
}
} catch (Throwable e) {
try {
logger.error("clean AdviceListener error", e);

@ -25,7 +25,6 @@ public class AdviceWeaver {
/**
*
*
* @param adviceId ID
* @param listener
*/
public static void reg(AdviceListener listener) {
@ -40,7 +39,7 @@ public class AdviceWeaver {
/**
*
*
* @param adviceId ID
* @param listener
*/
public static void unReg(AdviceListener listener) {
if (null != listener) {

@ -42,6 +42,7 @@ import com.alibaba.bytekit.asm.location.filter.InvokeContainLocationFilter;
import com.alibaba.bytekit.asm.location.filter.LocationFilter;
import com.alibaba.bytekit.utils.AsmOpUtils;
import com.alibaba.bytekit.utils.AsmUtils;
import com.taobao.arthas.common.Pair;
import com.taobao.arthas.core.GlobalOptions;
import com.taobao.arthas.core.advisor.SpyInterceptors.SpyInterceptor1;
import com.taobao.arthas.core.advisor.SpyInterceptors.SpyInterceptor2;
@ -76,6 +77,7 @@ public class Enhancer implements ClassFileTransformer {
private final Matcher methodNameMatcher;
private final EnhancerAffect affect;
private Set<Class<?>> matchingClasses = null;
private static final ClassLoader selfClassLoader = Enhancer.class.getClassLoader();
// 被增强的类的缓存
private final static Map<Class<?>/* Class */, Object> classBytesCache = new WeakHashMap<Class<?>, Object>();
@ -143,7 +145,7 @@ public class Enhancer implements ClassFileTransformer {
interceptorProcessors.addAll(defaultInterceptorClassParser.parse(SpyInterceptor3.class));
if (this.isTracing) {
if (this.skipJDKTrace == false) {
if (!this.skipJDKTrace) {
interceptorProcessors.addAll(defaultInterceptorClassParser.parse(SpyTraceInterceptor1.class));
interceptorProcessors.addAll(defaultInterceptorClassParser.parse(SpyTraceInterceptor2.class));
interceptorProcessors.addAll(defaultInterceptorClassParser.parse(SpyTraceInterceptor3.class));
@ -320,14 +322,35 @@ public class Enhancer implements ClassFileTransformer {
*
* @param classes
*/
private void filter(Set<Class<?>> classes) {
private List<Pair<Class<?>, String>> filter(Set<Class<?>> classes) {
List<Pair<Class<?>, String>> filteredClasses = new ArrayList<Pair<Class<?>, String>>();
final Iterator<Class<?>> it = classes.iterator();
while (it.hasNext()) {
final Class<?> clazz = it.next();
if (null == clazz || isSelf(clazz) || isUnsafeClass(clazz) || isUnsupportedClass(clazz) || isExclude(clazz)) {
boolean removeFlag = false;
if (null == clazz) {
removeFlag = true;
} else if (isSelf(clazz)) {
filteredClasses.add(new Pair<Class<?>, String>(clazz, "class loaded by arthas itself"));
removeFlag = true;
} else if (isUnsafeClass(clazz)) {
filteredClasses.add(new Pair<Class<?>, String>(clazz, "class loaded by Bootstrap Classloader, try to execute `options unsafe true`"));
removeFlag = true;
} else if (isExclude(clazz)) {
filteredClasses.add(new Pair<Class<?>, String>(clazz, "class is excluded"));
removeFlag = true;
} else {
Pair<Boolean, String> unsupportedResult = isUnsupportedClass(clazz);
if (unsupportedResult.getFirst()) {
filteredClasses.add(new Pair<Class<?>, String>(clazz, unsupportedResult.getSecond()));
removeFlag = true;
}
}
if (removeFlag) {
it.remove();
}
}
return filteredClasses;
}
private boolean isExclude(Class<?> clazz) {
@ -341,7 +364,7 @@ public class Enhancer implements ClassFileTransformer {
* Arthas
*/
private static boolean isSelf(Class<?> clazz) {
return null != clazz && isEquals(clazz.getClassLoader(), Enhancer.class.getClassLoader());
return null != clazz && isEquals(clazz.getClassLoader(), selfClassLoader);
}
/**
@ -354,31 +377,58 @@ public class Enhancer implements ClassFileTransformer {
/**
*
*/
private static boolean isUnsupportedClass(Class<?> clazz) {
return clazz.isArray() || (clazz.isInterface() && !GlobalOptions.isSupportDefaultMethod) || clazz.isEnum()
|| clazz.equals(Class.class) || clazz.equals(Integer.class) || clazz.equals(Method.class) || ClassUtils.isLambdaClass(clazz);
private static Pair<Boolean, String> isUnsupportedClass(Class<?> clazz) {
if (ClassUtils.isLambdaClass(clazz)) {
return new Pair<Boolean, String>(Boolean.TRUE, "class is lambda");
}
if (clazz.isInterface() && !GlobalOptions.isSupportDefaultMethod) {
return new Pair<Boolean, String>(Boolean.TRUE, "class is interface");
}
if (clazz.equals(Integer.class)) {
return new Pair<Boolean, String>(Boolean.TRUE, "class is java.lang.Integer");
}
if (clazz.equals(Class.class)) {
return new Pair<Boolean, String>(Boolean.TRUE, "class is java.lang.Class");
}
if (clazz.equals(Method.class)) {
return new Pair<Boolean, String>(Boolean.TRUE, "class is java.lang.Method");
}
if (clazz.isArray()) {
return new Pair<Boolean, String>(Boolean.TRUE, "class is array");
}
return new Pair<Boolean, String>(Boolean.FALSE, "");
}
/**
*
*
* @param inst inst
* @param adviceId ID
* @param isTracing
* @param skipJDKTrace JDK
* @param classNameMatcher
* @param methodNameMatcher
* @param maxNumOfMatchedClass class
* @return
* @throws UnmodifiableClassException
*/
public synchronized EnhancerAffect enhance(final Instrumentation inst) throws UnmodifiableClassException {
public synchronized EnhancerAffect enhance(final Instrumentation inst, int maxNumOfMatchedClass) throws UnmodifiableClassException {
// 获取需要增强的类集合
this.matchingClasses = GlobalOptions.isDisableSubClass
? SearchUtils.searchClass(inst, classNameMatcher)
: SearchUtils.searchSubClass(inst, SearchUtils.searchClass(inst, classNameMatcher));
if (matchingClasses.size() > maxNumOfMatchedClass) {
affect.setOverLimitMsg("The number of matched classes is " +matchingClasses.size()+ ", greater than the limit value " + maxNumOfMatchedClass + ". Try to change the limit with option '-m <arg>'.");
return affect;
}
// 过滤掉无法被增强的类
filter(matchingClasses);
List<Pair<Class<?>, String>> filtedList = filter(matchingClasses);
if (!filtedList.isEmpty()) {
for (Pair<Class<?>, String> filted : filtedList) {
logger.info("ignore class: {}, reason: {}", filted.getFirst().getName(), filted.getSecond());
}
}
logger.info("enhance matched classes: {}", matchingClasses);

@ -3,25 +3,10 @@ package com.taobao.arthas.core.command;
import java.util.ArrayList;
import java.util.List;
import com.taobao.arthas.core.command.basic1000.AuthCommand;
import com.taobao.arthas.core.command.basic1000.Base64Command;
import com.taobao.arthas.core.command.basic1000.CatCommand;
import com.taobao.arthas.core.command.basic1000.ClsCommand;
import com.taobao.arthas.core.command.basic1000.EchoCommand;
import com.taobao.arthas.core.command.basic1000.GrepCommand;
import com.taobao.arthas.core.command.basic1000.HelpCommand;
import com.taobao.arthas.core.command.basic1000.HistoryCommand;
import com.taobao.arthas.core.command.basic1000.KeymapCommand;
import com.taobao.arthas.core.command.basic1000.OptionsCommand;
import com.taobao.arthas.core.command.basic1000.PwdCommand;
import com.taobao.arthas.core.command.basic1000.ResetCommand;
import com.taobao.arthas.core.command.basic1000.SessionCommand;
import com.taobao.arthas.core.command.basic1000.StopCommand;
import com.taobao.arthas.core.command.basic1000.SystemEnvCommand;
import com.taobao.arthas.core.command.basic1000.SystemPropertyCommand;
import com.taobao.arthas.core.command.basic1000.TeeCommand;
import com.taobao.arthas.core.command.basic1000.VMOptionCommand;
import com.taobao.arthas.core.command.basic1000.VersionCommand;
import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.taobao.arthas.core.command.basic1000.*;
import com.taobao.arthas.core.command.hidden.JulyCommand;
import com.taobao.arthas.core.command.hidden.ThanksCommand;
import com.taobao.arthas.core.command.klass100.ClassLoaderCommand;
@ -46,7 +31,7 @@ import com.taobao.middleware.cli.annotations.Name;
* @author beiwei30 on 17/11/2016.
*/
public class BuiltinCommandPack implements CommandResolver {
private static final Logger logger = LoggerFactory.getLogger(BuiltinCommandPack.class);
private List<Command> commands = new ArrayList<Command>();
public BuiltinCommandPack(List<String> disabledCommands) {
@ -59,7 +44,7 @@ public class BuiltinCommandPack implements CommandResolver {
}
private void initCommands(List<String> disabledCommands) {
List<Class<? extends AnnotatedCommand>> commandClassList = new ArrayList<Class<? extends AnnotatedCommand>>(32);
List<Class<? extends AnnotatedCommand>> commandClassList = new ArrayList<Class<? extends AnnotatedCommand>>(33);
commandClassList.add(HelpCommand.class);
commandClassList.add(AuthCommand.class);
commandClassList.add(KeymapCommand.class);
@ -76,6 +61,7 @@ public class BuiltinCommandPack implements CommandResolver {
commandClassList.add(SqlProfilerCommand.class);
commandClassList.add(TimeTunnelCommand.class);
commandClassList.add(JvmCommand.class);
commandClassList.add(MemoryCommand.class);
commandClassList.add(PerfCounterCommand.class);
// commandClassList.add(GroovyScriptCommand.class);
commandClassList.add(OgnlCommand.class);
@ -107,6 +93,13 @@ public class BuiltinCommandPack implements CommandResolver {
commandClassList.add(ProfilerCommand.class);
commandClassList.add(VmToolCommand.class);
commandClassList.add(StopCommand.class);
try {
if (ClassLoader.getSystemClassLoader().getResource("jdk/jfr/Recording.class") != null) {
commandClassList.add(JFRCommand.class);
}
} catch (Throwable e) {
logger.error("This jdk version not support jfr command");
}
for (Class<? extends AnnotatedCommand> clazz : commandClassList) {
Name name = clazz.getAnnotation(Name.class);

@ -49,7 +49,7 @@ public class HistoryCommand extends AnnotatedCommand {
Session session = process.session();
//TODO 修改term history实现方式统一使用HistoryManager
Object termObject = session.get(Session.TTY);
if (termObject != null && termObject instanceof TermImpl) {
if (termObject instanceof TermImpl) {
TermImpl term = (TermImpl) termObject;
Readline readline = term.getReadline();
List<int[]> history = readline.getHistory();

@ -0,0 +1,427 @@
package com.taobao.arthas.core.command.basic1000;
import com.taobao.arthas.core.command.Constants;
import com.taobao.arthas.core.command.model.JFRModel;
import com.taobao.arthas.core.server.ArthasBootstrap;
import com.taobao.arthas.core.shell.cli.CliToken;
import com.taobao.arthas.core.shell.cli.Completion;
import com.taobao.arthas.core.shell.cli.CompletionUtils;
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.middleware.cli.annotations.Argument;
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 jdk.jfr.Configuration;
import jdk.jfr.Recording;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@Name("jfr")
@Summary("Java Flight Recorder Command")
@Description(Constants.EXAMPLE +
" jfr start # start a new JFR recording\n" +
" jfr start -n myRecording --duration 60s -f /tmp/myRecording.jfr \n" +
" jfr status # list all recordings\n" +
" jfr status -r 1 # list recording id = 1 \n" +
" jfr status --state running # list recordings state = running\n" +
" jfr stop -r 1 # stop a JFR recording to default file\n" +
" jfr stop -r 1 -f /tmp/myRecording.jfr\n" +
" jfr dump -r 1 # copy contents of a JFR recording to default file\n" +
" jfr dump -r 1 -f /tmp/myRecording.jfr\n" +
Constants.WIKI + Constants.WIKI_HOME + "jfr")
public class JFRCommand extends AnnotatedCommand {
private String cmd;
private String name;
private String settings;
private Boolean dumpOnExit;
private String delay;
private String duration;
private String filename;
private String maxAge;
private String maxSize;
private Long recording;
private String state;
private JFRModel result = new JFRModel();
private static Map<Long, Recording> recordings = new ConcurrentHashMap<Long, Recording>();
@Argument(index = 0, argName = "cmd", required = true)
@Description("command name (start status stop dump)")
public void setCmd(String cmd) {
this.cmd = cmd;
}
@Option(shortName = "n", longName = "name")
@Description("Name that can be used to identify recording, e.g. \"My Recording\"")
public void setName(String name) {
this.name = name;
}
@Option(shortName = "s", longName = "settings")
@Description("Settings file(s), e.g. profile or default. See JRE_HOME/lib/jfr (STRING , default)")
public void setSettings(String settings) {
this.settings = settings;
}
@Option(longName = "dumponexit")
@Description("Dump running recording when JVM shuts down (BOOLEAN, false)")
public void setDumpOnExit(Boolean dumpOnExit) {
this.dumpOnExit = dumpOnExit;
}
@Option(shortName = "d", longName = "delay")
@Description("Delay recording start with (s)econds, (m)inutes), (h)ours), or (d)ays, e.g. 5h. (NANOTIME, 0)")
public void setDelay(String delay) {
this.delay = delay;
}
@Option(longName = "duration")
@Description("Duration of recording in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 300s. (NANOTIME, 0)")
public void setDuration(String duration) {
this.duration = duration;
}
@Option(shortName = "f", longName = "filename")
@Description("Resulting recording filename, e.g. /tmp/MyRecording.jfr.")
public void setFilename(String filename) {
this.filename = filename;
}
@Option(longName = "maxage")
@Description("Maximum time to keep recorded data (on disk) in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or default for no limit (NANOTIME, 0)")
public void setMaxAge(String maxAge) {
this.maxAge = maxAge;
}
@Option(longName = "maxsize")
@Description("Maximum amount of bytes to keep (on disk) in (k)B, (M)B or (G)B, e.g. 500M, 0 for no limit (MEMORY SIZE, 250MB)")
public void setMaxSize(String maxSize) {
this.maxSize = maxSize;
}
@Option(shortName = "r", longName = "recording")
@Description("Recording number, or omit to see all recordings (LONG, -1)")
public void setRecording(Long recording) {
this.recording = recording;
}
@Option(longName = "state")
@Description("Query recordings by sate (new, delay, running, stopped, closed)")
public void setState(String state) {
this.state = state;
}
public String getCmd() {
return cmd;
}
public String getName() {
return name;
}
public String getSettings() {
return settings;
}
public Boolean isDumpOnExit() {
return dumpOnExit;
}
public String getDelay() {
return delay;
}
public String getDuration() {
return duration;
}
public String getFilename() {
return filename;
}
public String getMaxAge() {
return maxAge;
}
public String getMaxSize() {
return maxSize;
}
public Long getRecording() {
return recording;
}
public String getState() {
return state;
}
@Override
public void process(CommandProcess process) {
if ("start".equals(cmd)) {
Configuration c = null;
try {
if (getSettings() == null) {
setSettings("default");
}
c = Configuration.getConfiguration(settings);
} catch (Throwable e) {
process.end(-1, "Could not start recording, not able to read settings");
}
Recording r = new Recording(c);
if (getFilename() != null) {
try {
r.setDestination(Paths.get(getFilename()));
} catch (IOException e) {
r.close();
process.end(-1, "Could not start recording, not able to write to file " + getFilename() + e.getMessage());
}
}
if (getMaxSize() != null) {
try {
r.setMaxSize(parseSize(getMaxSize()));
} catch (Exception e) {
process.end(-1, e.getMessage());
}
}
if (getMaxAge() != null) {
try {
r.setMaxAge(Duration.ofNanos(parseTimespan(getMaxAge())));
} catch (Exception e) {
process.end(-1, e.getMessage());
}
}
if (isDumpOnExit() != false) {
r.setDumpOnExit(isDumpOnExit().booleanValue());
}
if (getDuration() != null) {
try {
r.setDuration(Duration.ofNanos(parseTimespan(getDuration())));
} catch (Exception e) {
process.end(-1, e.getMessage());
}
}
if (getName() == null) {
r.setName("Recording-" + r.getId());
} else {
r.setName(getName());
}
long id = r.getId();
recordings.put(id, r);
if (getDelay() != null) {
try {
r.scheduleStart(Duration.ofNanos(parseTimespan(getDelay())));
} catch (Exception e) {
process.end(-1, e.getMessage());
}
result.setJfrOutput("Recording " + r.getId() + " scheduled to start in " + getDelay());
} else {
r.start();
result.setJfrOutput("Started recording " + r.getId() + ".");
}
if (duration == null && maxAge == null && maxSize == null) {
result.setJfrOutput(" No limit specified, using maxsize=250MB as default.");
r.setMaxSize(250 * 1024L * 1024L);
}
if (filename != null && duration != null) {
result.setJfrOutput(" The result will be written to:\n" + filename);
}
} else if ("status".equals(cmd)) {
// list recording id = recording
if (getRecording() != null) {
Recording r = recordings.get(getRecording());
if (r == null) {
process.end(-1, "recording not exit");
}
printRecording(r);
} else {// list all recordings
List<Recording> recordingList;
if (state != null) {
recordingList = findRecordingByState(state);
} else {
recordingList = new ArrayList<Recording>(recordings.values());
}
if (recordingList.isEmpty()) {
process.end(-1, "No available recordings.\n Use jfr start to start a recording.\n");
} else {
for (Recording recording : recordingList) {
printRecording(recording);
}
}
}
} else if ("dump".equals(cmd)) {
if (recordings.isEmpty()) {
process.end(-1, "No recordings to dump. Use jfr start to start a recording.");
}
if (getRecording() != null) {
Recording r = recordings.get(getRecording());
if (r == null) {
process.end(-1, "recording not exit");
}
if (getFilename() == null) {
try {
setFilename(outputFile());
} catch (IOException e) {
process.end(-1, e.getMessage());
}
}
try {
r.dump(Paths.get(getFilename()));
} catch (IOException e) {
process.end(-1, "Could not to dump. " + e.getMessage());
}
result.setJfrOutput("Dump recording " + r.getId() + ", The result will be written to:\n" + getFilename());
} else {
process.end(-1, "Failed to dump. Please input recording id");
}
} else if ("stop".equals(cmd)) {
if (recordings.isEmpty()) {
process.end(-1, "No recordings to stop. Use jfr start to start a recording.");
}
if (getRecording() != null) {
Recording r = recordings.remove(getRecording());
if (r == null) {
process.end(-1, "recording not exit");
}
if ("CLOSED".equals(r.getState().toString()) || "STOPPED".equals(r.getState().toString())) {
process.end(-1, "Failed to stop recording, state can not be closed/stopped");
}
if (getFilename() == null) {
try {
setFilename(outputFile());
} catch (IOException e) {
process.end(-1, e.getMessage());
}
}
try {
r.setDestination(Paths.get(getFilename()));
} catch (IOException e) {
process.end(-1, "Failed to stop" + r.getName() + ". Could not set destination for " + filename + "to file" + e.getMessage());
}
r.stop();
result.setJfrOutput("Stop recording " + r.getId() + ", The result will be written to:\n" + getFilename());
r.close();
} else {
process.end(-1, "Failed to stop. please input recording id");
}
} else {
process.end(-1, "Please input correct jfr command (start status stop dump)");
}
process.appendResult(result);
process.end();
}
public long parseSize(String s) throws Exception {
s = s.toLowerCase();
if (s.endsWith("b")) {
return Long.parseLong(s.substring(0, s.length() - 1).trim());
} else if (s.endsWith("k")) {
return 1024 * Long.parseLong(s.substring(0, s.length() - 1).trim());
} else if (s.endsWith("m")) {
return 1024 * 1024 * Long.parseLong(s.substring(0, s.length() - 1).trim());
} else if (s.endsWith("g")) {
return 1024 * 1024 * 1024 * Long.parseLong(s.substring(0, s.length() - 1).trim());
} else {
try {
return Long.parseLong(s);
} catch (Exception e) {
throw new NumberFormatException("'" + s + "' is not a valid size. Shoule be numeric value followed by a unit, i.e. 20M. Valid units k, M, G");
}
}
}
public long parseTimespan(String s) throws Exception {
s = s.toLowerCase();
if (s.endsWith("s")) {
return TimeUnit.NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), TimeUnit.SECONDS);
} else if (s.endsWith("m")) {
return 60 * TimeUnit.NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), TimeUnit.SECONDS);
} else if (s.endsWith("h")) {
return 60 * 60 * TimeUnit.NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), TimeUnit.SECONDS);
} else if (s.endsWith("d")) {
return 24 * 60 * 60 * TimeUnit.NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), TimeUnit.SECONDS);
} else {
try {
return Long.parseLong(s);
} catch (NumberFormatException var2) {
throw new NumberFormatException("'" + s + "' is not a valid timespan. Shoule be numeric value followed by a unit, i.e. 20s. Valid units s, m, h and d.");
}
}
}
private List<Recording> findRecordingByState(String state) {
List<Recording> resultRecordingList = new ArrayList<Recording>();
Collection<Recording> recordingList = recordings.values();
for (Recording recording : recordingList) {
if (recording.getState().toString().toLowerCase().equals(state)) {
resultRecordingList.add(recording);
}
}
return resultRecordingList;
}
private void printRecording(Recording recording) {
String format = "Recording: recording=" + recording.getId() + " name=" + recording.getName() + "";
result.setJfrOutput(format);
Duration duration = recording.getDuration();
if (duration != null) {
result.setJfrOutput(" duration=" + duration.toString());
}
result.setJfrOutput(" (" + recording.getState().toString().toLowerCase() + ")\n");
}
private String outputFile() throws IOException {
if (this.filename == null) {
File outputPath = ArthasBootstrap.getInstance().getOutputPath();
if (outputPath != null) {
this.filename = new File(outputPath,
new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + ".jfr")
.getAbsolutePath();
} else {
this.filename = File.createTempFile("arthas-output", ".jfr").getAbsolutePath();
}
}
return filename;
}
@Override
public void complete(Completion completion) {
List<CliToken> tokens = completion.lineTokens();
String token = tokens.get(tokens.size() - 1).value();
if (token.startsWith("-")) {
super.complete(completion);
return;
}
List<String> cmd = Arrays.asList("start", "status", "dump", "stop");
CompletionUtils.complete(completion, cmd);
}
}

@ -55,7 +55,7 @@ public class KeymapCommand extends AnnotatedCommand {
continue;
}
String[] strings = line.split(":");
if (strings != null && strings.length == 2) {
if (strings.length == 2) {
table.row(strings[0], translate(strings[0]), strings[1]);
} else {
table.row(line);

@ -17,7 +17,7 @@ import com.taobao.middleware.cli.annotations.Summary;
* @author ralf0131 2017-01-09 14:03.
*/
@Name("sysprop")
@Summary("Display, and change the system properties.")
@Summary("Display and change the system properties.")
@Description(Constants.EXAMPLE + " sysprop\n"+ " sysprop file.encoding\n" + " sysprop production.mode true\n" +
Constants.WIKI + Constants.WIKI_HOME + "sysprop")
public class SystemPropertyCommand extends AnnotatedCommand {

@ -2,7 +2,7 @@ package com.taobao.arthas.core.command.basic1000;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.alibaba.arthas.deps.org.slf4j.Logger;
@ -77,7 +77,7 @@ public class VMOptionCommand extends AnnotatedCommand {
process.end(-1, "In order to change the system properties, you must specify the property value.");
return;
} else {
process.appendResult(new VMOptionModel(Arrays.asList(option)));
process.appendResult(new VMOptionModel(Collections.singletonList(option)));
}
} else {
VMOption vmOption = hotSpotDiagnosticMXBean.getVMOption(name);

@ -0,0 +1,25 @@
package com.taobao.arthas.core.command.express;
import java.util.Map;
import com.taobao.arthas.core.GlobalOptions;
import ognl.ObjectPropertyAccessor;
import ognl.OgnlException;
/**
*
* @author hengyunabc 2022-03-24
*
*/
public class ArthasObjectPropertyAccessor extends ObjectPropertyAccessor {
@Override
public Object setPossibleProperty(Map context, Object target, String name, Object value) throws OgnlException {
if (GlobalOptions.strict) {
throw new IllegalAccessError(GlobalOptions.STRICT_MESSAGE);
}
return super.setPossibleProperty(context, target, name, value);
}
}

@ -8,6 +8,7 @@ import ognl.DefaultMemberAccess;
import ognl.MemberAccess;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlRuntime;
/**
* @author ralf0131 2017-01-04 14:41.
@ -16,6 +17,7 @@ import ognl.OgnlContext;
public class OgnlExpress implements Express {
private static final MemberAccess MEMBER_ACCESS = new DefaultMemberAccess(true);
private static final Logger logger = LoggerFactory.getLogger(OgnlExpress.class);
private static final ArthasObjectPropertyAccessor OBJECT_PROPERTY_ACCESSOR = new ArthasObjectPropertyAccessor();
private Object bindObject;
private final OgnlContext context;
@ -25,6 +27,7 @@ public class OgnlExpress implements Express {
}
public OgnlExpress(ClassResolver classResolver) {
OgnlRuntime.setPropertyAccessor(Object.class, OBJECT_PROPERTY_ACCESSOR);
context = new OgnlContext();
context.setClassResolver(classResolver);
// allow private field access
@ -44,7 +47,7 @@ public class OgnlExpress implements Express {
@Override
public boolean is(String express) throws ExpressException {
final Object ret = get(express);
return null != ret && ret instanceof Boolean && (Boolean) ret;
return ret instanceof Boolean && (Boolean) ret;
}
@Override

@ -15,6 +15,7 @@ import com.taobao.arthas.core.shell.handlers.Handler;
import com.taobao.arthas.core.util.ClassUtils;
import com.taobao.arthas.core.util.ClassLoaderUtils;
import com.taobao.arthas.core.util.ResultUtils;
import com.taobao.arthas.core.util.StringUtils;
import com.taobao.arthas.core.util.affect.RowAffect;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Name;
@ -23,7 +24,8 @@ import com.taobao.middleware.cli.annotations.Summary;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -51,6 +53,7 @@ import java.util.TreeSet;
" classloader -a\n" +
" classloader -a -c 327a647b\n" +
" classloader -c 659e0bfd --load demo.MathGame\n" +
" classloader -u # url statistics\n" +
Constants.WIKI + Constants.WIKI_HOME + "classloader")
public class ClassLoaderCommand extends AnnotatedCommand {
@ -63,6 +66,8 @@ public class ClassLoaderCommand extends AnnotatedCommand {
private boolean includeReflectionClassLoader = true;
private boolean listClassLoader = false;
private boolean urlStat = false;
private String loadClass = null;
private volatile boolean isInterrupted = false;
@ -115,6 +120,12 @@ public class ClassLoaderCommand extends AnnotatedCommand {
this.loadClass = className;
}
@Option(shortName = "u", longName = "url-stat", flag = true)
@Description("Display classloader url statistics")
public void setUrlStat(boolean urlStat) {
this.urlStat = urlStat;
}
@Override
public void process(CommandProcess process) {
// ctrl-C support
@ -124,6 +135,15 @@ public class ClassLoaderCommand extends AnnotatedCommand {
Instrumentation inst = process.session().getInstrumentation();
if (urlStat) {
Map<ClassLoaderVO, ClassLoaderUrlStat> urlStats = this.urlStats(inst);
ClassLoaderModel model = new ClassLoaderModel();
model.setUrlStats(urlStats);
process.appendResult(model);
process.end();
return;
}
if (hashCode != null || classLoaderClass != null) {
classLoaderSpecified = true;
}
@ -136,7 +156,7 @@ public class ClassLoaderCommand extends AnnotatedCommand {
break;
}
}
} else if (targetClassLoader == null && classLoaderClass != null) {
} else if (classLoaderClass != null) {
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, classLoaderClass);
if (matchedClassLoaders.size() == 1) {
targetClassLoader = matchedClassLoaders.get(0);
@ -226,14 +246,14 @@ public class ClassLoaderCommand extends AnnotatedCommand {
private void processClassLoader(CommandProcess process, Instrumentation inst, ClassLoader targetClassLoader) {
RowAffect affect = new RowAffect();
if (targetClassLoader != null) {
if (targetClassLoader instanceof URLClassLoader) {
List<String> classLoaderUrls = getClassLoaderUrls(targetClassLoader);
affect.rCnt(classLoaderUrls.size());
if (classLoaderUrls.isEmpty()) {
URL[] classLoaderUrls = ClassLoaderUtils.getUrls(targetClassLoader);
if (classLoaderUrls != null) {
affect.rCnt(classLoaderUrls.length);
if (classLoaderUrls.length == 0) {
process.appendResult(new MessageModel("urls is empty."));
} else {
process.appendResult(new ClassLoaderModel().setUrls(classLoaderUrls));
affect.rCnt(classLoaderUrls.size());
process.appendResult(new ClassLoaderModel().setUrls(StringUtils.toStringList(classLoaderUrls)));
affect.rCnt(classLoaderUrls.length);
}
} else {
process.appendResult(new MessageModel("not a URLClassLoader."));
@ -273,7 +293,7 @@ public class ClassLoaderCommand extends AnnotatedCommand {
try {
Class<?> clazz = targetClassLoader.loadClass(this.loadClass);
process.appendResult(new MessageModel("load class success."));
ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, false);
ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, false, null);
process.appendResult(new ClassLoaderModel().setLoadClass(classInfo));
} catch (Throwable e) {
@ -383,18 +403,44 @@ public class ClassLoaderCommand extends AnnotatedCommand {
}
}
private static List<String> getClassLoaderUrls(ClassLoader classLoader) {
List<String> urlStrs = new ArrayList<String>();
if (classLoader instanceof URLClassLoader) {
URLClassLoader cl = (URLClassLoader) classLoader;
URL[] urls = cl.getURLs();
if (urls != null) {
for (URL url : urls) {
urlStrs.add(url.toString());
private Map<ClassLoaderVO, ClassLoaderUrlStat> urlStats(Instrumentation inst) {
Map<ClassLoaderVO, ClassLoaderUrlStat> urlStats = new HashMap<ClassLoaderVO, ClassLoaderUrlStat>();
Map<ClassLoader, Set<String>> usedUrlsMap = new HashMap<ClassLoader, Set<String>>();
for (Class<?> clazz : inst.getAllLoadedClasses()) {
ClassLoader classLoader = clazz.getClassLoader();
if (classLoader != null) {
ProtectionDomain protectionDomain = clazz.getProtectionDomain();
CodeSource codeSource = protectionDomain.getCodeSource();
if (codeSource != null) {
URL location = codeSource.getLocation();
if (location != null) {
Set<String> urls = usedUrlsMap.get(classLoader);
if (urls == null) {
urls = new HashSet<String>();
usedUrlsMap.put(classLoader, urls);
}
urls.add(location.toString());
}
}
}
}
return urlStrs;
for (Entry<ClassLoader, Set<String>> entry : usedUrlsMap.entrySet()) {
ClassLoader loader = entry.getKey();
Set<String> usedUrls = entry.getValue();
URL[] allUrls = ClassLoaderUtils.getUrls(loader);
List<String> unusedUrls = new ArrayList<String>();
if (allUrls != null) {
for (URL url : allUrls) {
String urlStr = url.toString();
if (!usedUrls.contains(urlStr)) {
unusedUrls.add(urlStr);
}
}
}
urlStats.put(ClassUtils.createClassLoaderVO(loader), new ClassLoaderUrlStat(usedUrls, unusedUrls));
}
return urlStats;
}
// 以树状列出ClassLoader的继承结构
@ -583,6 +629,36 @@ public class ClassLoaderCommand extends AnnotatedCommand {
}
}
public static class ClassLoaderUrlStat {
private Collection<String> usedUrls;
private Collection<String> unUsedUrls;
public ClassLoaderUrlStat() {
}
public ClassLoaderUrlStat(Collection<String> usedUrls, Collection<String> unUsedUrls) {
super();
this.usedUrls = usedUrls;
this.unUsedUrls = unUsedUrls;
}
public Collection<String> getUsedUrls() {
return usedUrls;
}
public void setUsedUrls(Collection<String> usedUrls) {
this.usedUrls = usedUrls;
}
public Collection<String> getUnUsedUrls() {
return unUsedUrls;
}
public void setUnUsedUrls(Collection<String> unUsedUrls) {
this.unUsedUrls = unUsedUrls;
}
}
public static class ClassLoaderStat {
private int loadedCount;
private int numberOfInstance;

@ -92,7 +92,7 @@ public class DumpClassCommand extends AnnotatedCommand {
}
@Option(shortName = "l", longName = "limit")
@Description("The limit of dump classes size, default value is 5")
@Description("The limit of dump classes size, default value is 50")
@DefaultValue("50")
public void setLimit(int limit) {
this.limit = limit;

@ -200,7 +200,7 @@ public class JadCommand extends AnnotatedCommand {
return ExitStatus.success();
} catch (Throwable t) {
logger.error("jad: fail to decompile class: " + c.getName(), t);
return ExitStatus.failure(-1, "jad: fail to decompile class: " + c.getName());
return ExitStatus.failure(-1, "jad: fail to decompile class: " + c.getName() + ", please check $HOME/logs/arthas/arthas.log for more details.");
}
}

@ -11,6 +11,7 @@ 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.ObjectVO;
import com.taobao.arthas.core.command.model.OgnlModel;
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
import com.taobao.arthas.core.shell.command.CommandProcess;
@ -30,7 +31,7 @@ import com.taobao.middleware.cli.annotations.Summary;
@Name("ognl")
@Summary("Execute ognl expression.")
@Description(Constants.EXAMPLE
+ " ognl '@java.lang.System@out.println(\"hello\")' \n"
+ " ognl '@java.lang.System@out.println(\"hello \\u4e2d\\u6587\")' \n"
+ " ognl -x 2 '@Singleton@getInstance()' \n"
+ " ognl '@Demo@staticFiled' \n"
+ " ognl '#value1=@System@getProperty(\"java.home\"), #value2=@System@getProperty(\"java.runtime.name\"), {#value1, #value2}'\n"
@ -103,8 +104,7 @@ public class OgnlCommand extends AnnotatedCommand {
try {
Object value = unpooledExpress.get(express);
OgnlModel ognlModel = new OgnlModel()
.setValue(value)
.setExpand(expand);
.setValue(new ObjectVO(value, expand));
process.appendResult(ognlModel);
process.end();
} catch (ExpressException e) {

@ -124,7 +124,7 @@ public class RetransformCommand extends AnnotatedCommand {
}
@Option(longName = "limit")
@Description("The limit of dump classes size, default value is 5")
@Description("The limit of dump classes size, default value is 50")
@DefaultValue("50")
public void setLimit(int limit) {
this.limit = limit;

@ -50,6 +50,7 @@ public class SearchClassCommand extends AnnotatedCommand {
private boolean isRegEx = false;
private String hashCode = null;
private String classLoaderClass;
private String classLoaderToString;
private Integer expand;
private int numberOfLimit = 100;
@ -101,14 +102,27 @@ public class SearchClassCommand extends AnnotatedCommand {
this.numberOfLimit = numberOfLimit;
}
@Option(shortName = "cs", longName = "classLoaderStr")
@Description("The return value of the special class's ClassLoader#toString().")
public void setClassLoaderToString(String classLoaderToString) {
this.classLoaderToString = classLoaderToString;
}
@Override
public void process(final CommandProcess process) {
// TODO: null check
RowAffect affect = new RowAffect();
Instrumentation inst = process.session().getInstrumentation();
if (hashCode == null && classLoaderClass != null) {
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, classLoaderClass);
if (hashCode == null && (classLoaderClass != null || classLoaderToString != null)) {
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoader(inst, classLoaderClass, classLoaderToString);
String tips = "";
if (classLoaderClass != null) {
tips = "class name: " + classLoaderClass;
}
if (classLoaderToString != null) {
tips = tips + (StringUtils.isEmpty(tips) ? "ClassLoader#toString(): " : ", ClassLoader#toString(): ") + classLoaderToString;
}
if (matchedClassLoaders.size() == 1) {
hashCode = Integer.toHexString(matchedClassLoaders.get(0).hashCode());
} else if (matchedClassLoaders.size() > 1) {
@ -117,10 +131,10 @@ public class SearchClassCommand extends AnnotatedCommand {
.setClassLoaderClass(classLoaderClass)
.setMatchedClassLoaders(classLoaderVOList);
process.appendResult(searchclassModel);
process.end(-1, "Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'");
process.end(-1, "Found more than one classloader by " + tips + ", please specify classloader with '-c <classloader hash>'");
return;
} else {
process.end(-1, "Can not find classloader by class name: " + classLoaderClass + ".");
process.end(-1, "Can not find classloader by " + tips + ".");
return;
}
}
@ -140,8 +154,8 @@ public class SearchClassCommand extends AnnotatedCommand {
return;
}
for (Class<?> clazz : matchedClasses) {
ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, isField);
process.appendResult(new SearchClassModel(classInfo, isDetail, isField, expand));
ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, isField, expand);
process.appendResult(new SearchClassModel(classInfo, isDetail, isField));
}
} else {
int pageSize = 256;

@ -115,6 +115,28 @@ public class LoggerCommand extends AnnotatedCommand {
@Override
public void process(CommandProcess process) {
// 所有代码都用 hashCode 来定位classloader如果有指定 classLoaderClass则尝试用 classLoaderClass 找到对应 classloader 的 hashCode
if (hashCode == null && classLoaderClass != null) {
Instrumentation inst = process.session().getInstrumentation();
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst,
classLoaderClass);
if (matchedClassLoaders.size() == 1) {
hashCode = Integer.toHexString(matchedClassLoaders.get(0).hashCode());
} else if (matchedClassLoaders.size() > 1) {
Collection<ClassLoaderVO> classLoaderVOList = ClassUtils
.createClassLoaderVOList(matchedClassLoaders);
LoggerModel loggerModel = new LoggerModel().setClassLoaderClass(classLoaderClass)
.setMatchedClassLoaders(classLoaderVOList);
process.appendResult(loggerModel);
process.end(-1,
"Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'");
return;
} else {
process.end(-1, "Can not find classloader by class name: " + classLoaderClass + ".");
return;
}
}
// 每个分支中调用process.end()结束执行
if (this.name != null && this.level != null) {
level(process);
@ -126,66 +148,67 @@ public class LoggerCommand extends AnnotatedCommand {
public void level(CommandProcess process) {
Instrumentation inst = process.session().getInstrumentation();
boolean result = false;
// 如果不指定 classloader则默认用 SystemClassLoader
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
if (hashCode != null) {
classLoader = ClassLoaderUtils.getClassLoader(inst, hashCode);
if (classLoader == null) {
process.end(-1, "Can not find classloader by hashCode: " + hashCode + ".");
return;
}
}
LoggerTypes loggerTypes = findLoggerTypes(process.session().getInstrumentation(), classLoader);
if (loggerTypes.contains(LoggerType.LOG4J)) {
try {
Boolean updateResult = this.updateLevel(inst, Log4jHelper.class);
Boolean updateResult = this.updateLevel(inst, classLoader, Log4jHelper.class);
if (Boolean.TRUE.equals(updateResult)) {
result = true;
}
} catch (Throwable e) {
logger.error("logger command update log4j level error", e);
}
}
if (loggerTypes.contains(LoggerType.LOGBACK)) {
try {
Boolean updateResult = this.updateLevel(inst, LogbackHelper.class);
Boolean updateResult = this.updateLevel(inst, classLoader, LogbackHelper.class);
if (Boolean.TRUE.equals(updateResult)) {
result = true;
}
} catch (Throwable e) {
logger.error("logger command update logback level error", e);
}
}
if (loggerTypes.contains(LoggerType.LOG4J2)) {
try {
Boolean updateResult = this.updateLevel(inst, Log4j2Helper.class);
Boolean updateResult = this.updateLevel(inst, classLoader, Log4j2Helper.class);
if (Boolean.TRUE.equals(updateResult)) {
result = true;
}
} catch (Throwable e) {
logger.error("logger command update log4j2 level error", e);
}
}
if (result) {
process.end(0, "Update logger level success.");
} else {
process.end(-1, "Update logger level fail. Try to specify the classloader with the -c option. Use `sc -d CLASSNAME` to find out the classloader hashcode.");
process.end(-1,
"Update logger level fail. Try to specify the classloader with the -c option. Use `sc -d CLASSNAME` to find out the classloader hashcode.");
}
}
public void loggers(CommandProcess process) {
Map<ClassLoader, LoggerTypes> classLoaderLoggerMap = new LinkedHashMap<ClassLoader, LoggerTypes>();
// 如果不指定 classloader则打印所有 classloader 里的 logger 信息
for (Class<?> clazz : process.session().getInstrumentation().getAllLoadedClasses()) {
String className = clazz.getName();
ClassLoader classLoader = clazz.getClassLoader();
if (hashCode == null && classLoaderClass != null) {
Instrumentation inst = process.session().getInstrumentation();
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, classLoaderClass);
if (matchedClassLoaders.size() == 1) {
hashCode = Integer.toHexString(matchedClassLoaders.get(0).hashCode());
} else if (matchedClassLoaders.size() > 1) {
Collection<ClassLoaderVO> classLoaderVOList = ClassUtils.createClassLoaderVOList(matchedClassLoaders);
LoggerModel loggerModel = new LoggerModel()
.setClassLoaderClass(classLoaderClass)
.setMatchedClassLoaders(classLoaderVOList);
process.appendResult(loggerModel);
process.end(-1, "Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'");
return;
} else {
process.end(-1, "Can not find classloader by class name: " + classLoaderClass + ".");
return;
}
}
// if special classloader
if (this.hashCode != null && !this.hashCode.equals(StringUtils.classLoaderHash(clazz))) {
continue;
@ -197,13 +220,7 @@ public class LoggerCommand extends AnnotatedCommand {
loggerTypes = new LoggerTypes();
classLoaderLoggerMap.put(classLoader, loggerTypes);
}
if ("org.apache.log4j.Logger".equals(className)) {
loggerTypes.addType(LoggerType.LOG4J);
} else if ("ch.qos.logback.classic.Logger".equals(className)) {
loggerTypes.addType(LoggerType.LOGBACK);
} else if ("org.apache.logging.log4j.Logger".equals(className)) {
loggerTypes.addType(LoggerType.LOG4J2);
}
updateLoggerType(loggerTypes, classLoader, className);
}
}
@ -230,33 +247,72 @@ public class LoggerCommand extends AnnotatedCommand {
process.end();
}
private static String helperClassNameWithClassLoader(ClassLoader classLoader, Class<?> helperClass) {
private LoggerTypes findLoggerTypes(Instrumentation inst, ClassLoader classLoader) {
LoggerTypes loggerTypes = new LoggerTypes();
for (Class<?> clazz : inst.getAllLoadedClasses()) {
if(classLoader == clazz.getClassLoader()) {
updateLoggerType(loggerTypes, classLoader, clazz.getName());
}
}
return loggerTypes;
}
private void updateLoggerType(LoggerTypes loggerTypes, ClassLoader classLoader, String className) {
if ("org.apache.log4j.Logger".equals(className)) {
// 判断 org.apache.log4j.AsyncAppender 是否存在,如果存在则是 log4j不是slf4j-over-log4j
try {
if (classLoader.getResource("org/apache/log4j/AsyncAppender.class") != null) {
loggerTypes.addType(LoggerType.LOG4J);
}
} catch (Throwable e) {
// ignore
}
} else if ("ch.qos.logback.classic.Logger".equals(className)) {
try {
if (classLoader.getResource("ch/qos/logback/core/Appender.class") != null) {
loggerTypes.addType(LoggerType.LOGBACK);
}
} catch (Throwable e) {
// ignore
}
} else if ("org.apache.logging.log4j.Logger".equals(className)) {
try {
if (classLoader.getResource("org/apache/logging/log4j/core/LoggerContext.class") != null) {
loggerTypes.addType(LoggerType.LOG4J2);
}
} catch (Throwable e) {
// ignore
}
}
}
private static Class<?> helperClassNameWithClassLoader(ClassLoader classLoader, Class<?> helperClass) {
String classLoaderHash = ClassLoaderUtils.classLoaderHash(classLoader);
String className = helperClass.getName();
// if want to debug, change to return className
return className + arthasClassLoaderHash + classLoaderHash;
}
@SuppressWarnings("unchecked")
private Map<String, Map<String, Object>> loggerInfo(ClassLoader classLoader, Class<?> helperClass) {
Map<String, Map<String, Object>> loggers = Collections.emptyMap();
String helperClassName = className + arthasClassLoaderHash + classLoaderHash;
String helperClassName = helperClassNameWithClassLoader(classLoader, helperClass);
try {
classLoader.loadClass(helperClassName);
return classLoader.loadClass(helperClassName);
} catch (ClassNotFoundException e) {
try {
byte[] helperClassBytes = AsmRenameUtil.renameClass(classToBytesMap.get(helperClass),
helperClass.getName(), helperClassName);
ReflectUtils.defineClass(helperClassName, helperClassBytes, classLoader);
return ReflectUtils.defineClass(helperClassName, helperClassBytes, classLoader);
} catch (Throwable e1) {
logger.error("arthas loggger command try to define helper class error: " + helperClassName,
e1);
}
}
return null;
}
@SuppressWarnings("unchecked")
private Map<String, Map<String, Object>> loggerInfo(ClassLoader classLoader, Class<?> helperClass) {
Map<String, Map<String, Object>> loggers = Collections.emptyMap();
try {
Class<?> clazz = classLoader.loadClass(helperClassName);
Class<?> clazz = helperClassNameWithClassLoader(classLoader, helperClass);
Method getLoggersMethod = clazz.getMethod("getLoggers", new Class<?>[]{String.class, boolean.class});
loggers = (Map<String, Map<String, Object>>) getLoggersMethod.invoke(null,
new Object[]{name, includeNoAppender});
@ -287,18 +343,10 @@ public class LoggerCommand extends AnnotatedCommand {
return classLoader == null ? null : classLoader.toString();
}
private Boolean updateLevel(Instrumentation inst, Class<?> helperClass) throws Exception {
ClassLoader classLoader = null;
if (hashCode == null) {
classLoader = ClassLoader.getSystemClassLoader();
} else {
classLoader = ClassLoaderUtils.getClassLoader(inst, hashCode);
}
Class<?> clazz = classLoader.loadClass(helperClassNameWithClassLoader(classLoader, helperClass));
private Boolean updateLevel(Instrumentation inst, ClassLoader classLoader, Class<?> helperClass) throws Exception {
Class<?> clazz = helperClassNameWithClassLoader(classLoader, helperClass);
Method updateLevelMethod = clazz.getMethod("updateLevel", new Class<?>[]{String.class, String.class});
return (Boolean) updateLevelMethod.invoke(null, new Object[]{this.name, this.level});
}
static enum LoggerType {

@ -1,6 +1,7 @@
package com.taobao.arthas.core.command.model;
import com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderStat;
import com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderUrlStat;
import java.util.List;
import java.util.Map;
@ -24,6 +25,9 @@ public class ClassLoaderModel extends ResultModel {
private Collection<ClassLoaderVO> matchedClassLoaders;
private String classLoaderClass;
//urls stat
private Map<ClassLoaderVO, ClassLoaderUrlStat> urlStats;
public ClassLoaderModel() {
}
@ -112,4 +116,13 @@ public class ClassLoaderModel extends ResultModel {
this.matchedClassLoaders = matchedClassLoaders;
return this;
}
public Map<ClassLoaderVO, ClassLoaderUrlStat> getUrlStats() {
return urlStats;
}
public void setUrlStats(Map<ClassLoaderVO, ClassLoaderUrlStat> urlStats) {
this.urlStats = urlStats;
}
}

@ -20,6 +20,7 @@ public class EnhancerAffectVO {
private Throwable throwable;
private List<String> classDumpFiles;
private List<String> methods;
private String overLimitMsg;
public EnhancerAffectVO(EnhancerAffect affect) {
this.cost = affect.cost();
@ -27,6 +28,7 @@ public class EnhancerAffectVO {
this.methodCount = affect.mCnt();
this.listenerId = affect.getListenerId();
this.throwable = affect.getThrowable();
this.overLimitMsg = affect.getOverLimitMsg();
if (GlobalOptions.isDump) {
classDumpFiles = new ArrayList<String>();
@ -87,4 +89,12 @@ public class EnhancerAffectVO {
public void setMethods(List<String> methods) {
this.methods = methods;
}
public void setOverLimitMsg(String overLimitMsg) {
this.overLimitMsg = overLimitMsg;
}
public String getOverLimitMsg() {
return overLimitMsg;
}
}

@ -8,7 +8,7 @@ public class FieldVO {
private String type;
private String modifier;
private String[] annotations;
private Object value;
private ObjectVO value;
private boolean isStatic;
public String getName() {
@ -35,11 +35,11 @@ public class FieldVO {
this.modifier = modifier;
}
public Object getValue() {
public ObjectVO getValue() {
return value;
}
public void setValue(Object value) {
public void setValue(ObjectVO value) {
this.value = value;
}
@ -58,4 +58,5 @@ public class FieldVO {
public void setStatic(boolean aStatic) {
isStatic = aStatic;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save