文章目录
序言
模拟一个线程
我们知道,java为我们提供了Thread线程类操作线程,那么我们如何不使用Thread实现线程呢?我们可以手动去调用操作系统的线程方法,操作流程图如下:
- com.cbl.thread.ThreadTest.java
public class ThreadTest {
// java使用jni调用native方法,lib名为libCThreadTestNative.so去掉lib前缀,lib由CThreadTest.c在以下步骤生成
static {
System.loadLibrary("CThreadTestNative");
}
public native void start1();
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
threadTest.start1();
}
}
- 编译ThreadTest.java得到com_cbl_thread_ThreadTest.h
javac -h . ThreadTest.java
- com.cbl.thread.CThreadTest.c
// 该类的核心是pthread_create方法,该方法传递一个回调方法,可以把这个回调方法看作是线程的执行逻辑,类似run方法
#include <pthread.h>
#include <stdio.h>
#include "com_cbl_thread_ThreadTest.h" // 该文件由ThreadTest.java编译过来
pthread_t pid;
// 该方法为回调方法,类似于java启动线程后去执行run方法。
void* thread_entity(void* args) {
while (1) {
usleep(100);
printf("开启线程");
}
}
// 查看com_cbl_thread_ThreadTest.h并把JNIEXPORT方法体复制到这里
JNIEXPORT void JNICALL Java_com_cbl_thread_ThreadTest_start1(JNIEnv *env, jobject c1) {
pthread_create(&pid, NULL, thread_entity, NULL);
while (1) {
usleep(1000);
printf("main\n");
}
}
int main() {
return 0;
}
- 编译CThreadTest.c得到.so文件
gcc -fPIC -I /home/cbl/develop/jdk/jdk1.8.0_251/include -I /home/cbl/develop/jdk/jdk1.8.0_251/include/linux -shared -o libCThreadTestNative.so CThreadTest.c
- 把libCThreadTestNative.so文件放到linux库
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/cbl/proj/threadTest/com/cbl/thread/libCThreadTestNative.so
- 执行ThreadTest.class,最终结果是主线程和子线程交替打印。
java -classpath /home/cbl/proj/threadTest com.cbl.thread.ThreadTest
Java线程的本质
当我们不用Thread类去启动线程时,我们应该都可以猜到,Thread.start()方法其实调用了操作系统的p_thread_create()方法,run方法又作为p_thread_create()的回调方法,所以能够被执行到。
查看start方法源码,是一个本地方法,是不是跟我们上面的start1()很像?
private native void start0();
调试JDK源码
这里我们尝试去编译openjdk9,需要jdk8环境的支持,即官网所说的boot jdk
,openjdk9的源码可以在gitee下载。编译成功后可以看到build/linux-x86_64-normal-server-release目录。
配置jdk8环境
- sudo vim /etc/profile
JAVA_HOME=/home/cbl/develop/jdk/jdk1.8.0_251
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
export PATH JAVA_HOME CLASSPATH
source /etc/profile
编译openjdk9
需要上一个版本的环境,官网说的Boot JDK
即jdk1.8。gitee下载openjdk9的源码,解压进入openjdk9目录,执行。
为什么不用openjdk11+呢,因为执行make images
时踩过坑,找不到jre/lib/ext目录
bash configure
按照提示安装缺失的依赖
sudo yum -y groupinstall "Development Tools"
sudo yum -y install libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel
sudo yum -y install cups-devel
sudo yum -y install fontconfig-devel
sudo yum -y install alsa-lib-devel
sudo yum -y install elfutils-libelf-devel
make images
遇到了class JdiDefaultExecutionControl is public, should be declared in a file named JdiDefaultExecutionControl.java
错误,只需要把java源文件名的JDI改成Jdi即可,算是jdk9的bug?
编译完成后,使用以下命令验证
./build/*/images/jdk/bin/java -version
测试(好像报错了)
make run-test-tier1
linux安装clion
官网下载clion的linux包,解压
- 安装cmake
wget "https://cmake.org/files/v3.19/cmake-3.19.0-rc1.tar.gz"
cd cmake-3.10.0-rc3/
./bootstrap
gmake
gmake install
- 启动(需要配置xming),然后系统自动打开xming,即可看到图形界面了
./home/cbl/develop/clion/bin/clion.sh
使用Clion打开jdk9目录,设置run configuration
–> cmake application
–> executable:build/linux-x86_64-normal-server-release/jdk/bin/java
–> program arguments:-version
开始调试java的start方法
创建一个简单的thread类,javac xxx.java编译,然后放到clion的jdk12目录下jdk12/build/linux-x86_64-server-slowdebug/jdk/bin替换com文件夹,修改run configuration,program arguments改为com.xxx.xxx.Xxx
找到os_linux.cpp#pthread_attr_setguardsize方法,打断点
jvm.cpp#JVM_ENTRY
JVM_StartThread
其他资料
vmware设置固定ip
-
设置NAT网络
-
修改虚拟网络编辑器:
编辑->虚拟网络编辑器->VMnet8->子网IP:192.168.118.0 子网掩码->255.255.255.0
NAT设置->网关IP:192.168.118.2 -
修改ifcfg-ens33
sudo vim /etc/sysconfig/network-scripts/ifcfg-ens33
BOOTPROTO=static
IPADDR=192.168.118.10
NETMASK=255.255.255.0
GATEWAY=192.168.118.2
DNS1=114.114.114.114
ONBOOT=yes
- 重启网络
service network restart
centos安装图形界面
yum groupinstall "GNOME Desktop" "Graphical Administration Tools"
# 下面几个命令其实我不怎么用,都是使用xming运行图形界面的
systemctl set-default multi-user.target
systemctl set-default graphical.target
startx
xming+xshell打开命令行
- 安装xming,启动xlaunch,一路next
- 打开xshell会话->属性->SSH->隧道->X DISPLAY,改成localhost:0.0
- 修改xming目录下的X0.hosts,加上centos的ip
- 进入xshell,执行
export DISPLAY=192.168.118.10:0.0