歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> jsvc 啟動Java 在Linux下的實現原理

jsvc 啟動Java 在Linux下的實現原理

日期:2017/3/1 10:06:04   编辑:Linux編程

jsvc 是在apache的daemon項目下開源項目,主要功能可以使一些運行在普通用戶下的java進程獲取一些root權限下的權利,比如端口在1024下等。

如何運行

在自己的java代碼中,實現start, init , stop,destroy的方法,將自己的編譯打成jar文件, 通過調用jsvc 來啟動

./jsvc -java-home /usr/java/jdk1.7.0_09/ -user nobody -pidfile /opt/apache-tomcat_1/logs/catalina-daemon1.pid -wait 10 -errfile "/tmp/error" -outfile "/tmp/output" -debug -classpath /root/test.jar:/root/commons-daemon.jar test

幾個注意點:

commons_daemon.jar文件是用於調用你的class文件,

關於-java-home, 在這裡有一個bug(https://issues.apache.org/jira/browse/DAEMON-268),哪怕指定,也會指定為默認的/usr/java

其他的請參考jsvc --help

實現原理

jsvc 是一個源碼是c的程序,通過fork出子進程去啟動java,而進程成為控制進程,可以實現監視java子進程的目地。

改變啟動虛擬機的進程的用戶id, 和用戶組

通過調用setgid,setuid來改變當前進程的用戶id,和組,這裡要注意的是當改變用戶id,和組的時候,當前進程會改變進程的capability, 所以需要reset 進程的capability。

查看進程的capability 可以通過調用內核調用 __NR_capget / __NR_capset 的方式

static int get_legacy_caps(){
struct __user_cap_header_struct caphead;
struct __user_cap_data_struct cap;
memset(&caphead, 0, sizeof caphead);
caphead.version = LEGACY_CAP_VERSION;
if (syscall(__NR_capget, &caphead, &cap) < 0)
log_error("capget failed: %m");
log_debug("PID is %d print the cap 0x%x, 0x%x, 0x%x\n", getpid(), cap.effective, cap.permitted, cap.inheritable);
return 0;
}

啟動java

通過調用JNI_CreateJavaVM 啟動虛擬機器,同時調用包common-daemon裡的DaemonLoader class, 調用你所寫的類中的start,...這些方法。

碰到的問題

在jsvc 裡在啟動java以後就將jvm的虛擬機的進程的capability 設置成了0, 導致在虛擬機裡的創建線程受到max process 的控制, ulimit -u

已經創建issue: https://issues.apache.org/jira/browse/DAEMON-270, 短期解決辦法可以設置ulimit 到比較大的值。

Copyright © Linux教程網 All Rights Reserved