日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Signal实例

發布時間:2024/4/17 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Signal实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


http://wangym.iteye.com/blog/733693

TimYang在博文《降低應用latency方法談》 中提到對Java方法進行Profiling,在某些場景更傾向于采用純Java工具類的方法,比如通過給進程發Signals來實現,以求動態地打開或關閉Profiler。

?

感覺這個思路不錯,以下是一個大致實例:

?

SignalTest.java

?

Java代碼 ?
  • /**?
  • ?*??
  • ?*/??
  • package?signal;??
  • ??
  • import?java.util.Observable;??
  • import?java.util.Observer;??
  • import?sun.misc.Signal;??
  • import?sun.misc.SignalHandler;??
  • ??
  • /**?
  • ?*?@author?xuanyin?
  • ?*??
  • ?*/??
  • public?class?SignalTest?implements?Observer?{??
  • ??
  • ????/**?
  • ?????*?@param?args?
  • ?????*/??
  • ????public?static?void?main(String[]?args)?{??
  • ??
  • ????????new?SignalTest().go();??
  • ????}??
  • ??
  • ????private?void?go()?{??
  • ??
  • ????????try?{??
  • ??
  • ????????????HandlerTest?sh?=?new?HandlerTest();??
  • ????????????sh.addObserver(this);??
  • ????????????sh.handleSignal("HUP");??
  • ????????????sh.handleSignal("BUS");??
  • ????????????System.out.println("Sleeping?for?60?seconds:?hit?me?with?signals!");??
  • ????????????Thread.sleep(60000);??
  • ??
  • ????????}?catch?(Throwable?x)?{??
  • ??
  • ????????????x.printStackTrace();??
  • ????????}??
  • ????}??
  • ??
  • ????/**?
  • ?????*??
  • ?????*/??
  • ????@Override??
  • ????public?void?update(Observable?arg0,?Object?arg1)?{??
  • ??
  • ????????System.out.println("Received?signal:?"?+?arg1);??
  • ????}??
  • ??
  • ????/**?
  • ?????*?HandlerTest?Class?
  • ?????*/??
  • ????class?HandlerTest?extends?Observable?implements?SignalHandler?{??
  • ??
  • ????????@Override??
  • ????????public?void?handle(Signal?signal)?{??
  • ??
  • ????????????setChanged();??
  • ????????????notifyObservers(signal);??
  • ????????}??
  • ??
  • ????????/**?
  • ?????????*??
  • ?????????*?@param?signalName?
  • ?????????*?@throws?IllegalArgumentException?
  • ?????????*/??
  • ????????public?void?handleSignal(String?signalName)?throws?IllegalArgumentException?{??
  • ??
  • ????????????try?{??
  • ??
  • ????????????????Signal.handle(new?Signal(signalName),?this);??
  • ??
  • ????????????}?catch?(IllegalArgumentException?x)?{??
  • ??
  • ????????????????throw?x;??
  • ??
  • ????????????}?catch?(Throwable?x)?{??
  • ??
  • ????????????????throw?new?IllegalArgumentException("Signal?unsupported:?"+signalName,?x);??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • }??
  • /*** */ package signal;import java.util.Observable; import java.util.Observer; import sun.misc.Signal; import sun.misc.SignalHandler;/*** @author xuanyin* */ public class SignalTest implements Observer {/*** @param args*/public static void main(String[] args) {new SignalTest().go();}private void go() {try {HandlerTest sh = new HandlerTest();sh.addObserver(this);sh.handleSignal("HUP");sh.handleSignal("BUS");System.out.println("Sleeping for 60 seconds: hit me with signals!");Thread.sleep(60000);} catch (Throwable x) {x.printStackTrace();}}/*** */@Overridepublic void update(Observable arg0, Object arg1) {System.out.println("Received signal: " + arg1);}/*** HandlerTest Class*/class HandlerTest extends Observable implements SignalHandler {@Overridepublic void handle(Signal signal) {setChanged();notifyObservers(signal);}/*** * @param signalName* @throws IllegalArgumentException*/public void handleSignal(String signalName) throws IllegalArgumentException {try {Signal.handle(new Signal(signalName), this);} catch (IllegalArgumentException x) {throw x;} catch (Throwable x) {throw new IllegalArgumentException("Signal unsupported: "+signalName, x);}}}}

    ?

    首先運行執行上述程序,然后查看其系統進程號。

    如,若是4089,則在終端中執行kill -s BUS 4089

    Java程序輸出:Received signal: SIGBUS

    ?

    信號具有平臺相關性,不同平臺下能使用的信號種類是有差異的。

    ?

    Linux下支持的信號:

    SEGV, ILL, FPE, BUS, SYS, CPU, FSZ, ABRT, INT, TERM, HUP, USR1, USR2, QUIT, BREAK, TRAP, PIPE

    Windows下支持的信號:

    SEGV, ILL, FPE, ABRT, INT, TERM, BREAK

    ?

    不足之處歡迎大家留言指正:)


    ======================

    http://blog.csdn.net/raintungli/article/details/7310141

    在java 中調用Signal的方法handle可以去注冊一個信號的處理函數,方法的如下:

    [java] view plaincopyprint?
  • ?public?static?synchronized?SignalHandler?handle(Signal?sig,???
  • ????????????????????????????SignalHandler?handler)?{??
  • ....??
  • }??
  • public static synchronized SignalHandler handle(Signal sig, SignalHandler handler) { .... }


    比如常用的addShutdownHook鉤子函數里,就是在?Terminator.setup();的時候將Shutdown.exit 的函數注冊到了信號SHUTDOWN1_SIGNAL(SIGHUP),SHUTDOWN2_SIGNAL(SIGINT),SHUTDOWN3_SIGNAL(SIGTERM)中,當線程接受到信號時,通過調用函數Shutdown.exit的調用hook中的鉤子函數。

    在筆者的文章(java 中關于信號的處理在linux下的實現)也提到jdk如何處理信號的,那么調用handle里是不是直接就把這個方法注冊進了信號處理呢?

    請注意,handle是一個java的方法,而注冊信號函數是c的代碼,顯然不能簡單的將java的方法直接提供給c調用,其次信號處理函數是在內核態中處理,安全性和執行時間的長短將影響到內核的信號調度。

    先看java源碼,如下面所示

    [java] view plaincopyprint?
  • ?public?static?synchronized?SignalHandler?handle(Signal?sig,???
  • ????????????????????????SignalHandler?handler)???
  • throws?IllegalArgumentException?{??
  • long?newH?=?(handler?instanceof?NativeSignalHandler)?????
  • ??????????????((NativeSignalHandler)handler).getHandler()?:?2;??
  • long?oldH?=?handle0(sig.number,?newH);??
  • if?(oldH?==?-1)?{??
  • ????throw?new?IllegalArgumentException??
  • ????("Signal?already?used?by?VM:?"?+?sig);??
  • }??
  • signals.put(new?Integer(sig.number),?sig);??
  • synchronized?(handlers)?{??
  • ????SignalHandler?oldHandler?=?(SignalHandler)handlers.get(sig);??
  • ????handlers.remove(sig);??
  • ????if?(newH?==?2)?{??
  • ????????handlers.put(sig,?handler);???????????
  • ????}??
  • ????if?(oldH?==?0)?{??
  • ????????return?SignalHandler.SIG_DFL;??
  • ????}?else?if?(oldH?==?1)?{??
  • ????????return?SignalHandler.SIG_IGN;??
  • ????}?else?if?(oldH?==?2)?{??
  • ????????return?oldHandler;??
  • ????}?else?{??
  • ????????return?new?NativeSignalHandler(oldH);??
  • ????}??
  • }??
  • ???}??
  • public static synchronized SignalHandler handle(Signal sig, SignalHandler handler) throws IllegalArgumentException {long newH = (handler instanceof NativeSignalHandler) ? ((NativeSignalHandler)handler).getHandler() : 2;long oldH = handle0(sig.number, newH);if (oldH == -1) {throw new IllegalArgumentException("Signal already used by VM: " + sig);}signals.put(new Integer(sig.number), sig);synchronized (handlers) {SignalHandler oldHandler = (SignalHandler)handlers.get(sig);handlers.remove(sig);if (newH == 2) {handlers.put(sig, handler); }if (oldH == 0) {return SignalHandler.SIG_DFL;} else if (oldH == 1) {return SignalHandler.SIG_IGN;} else if (oldH == 2) {return oldHandler;} else {return new NativeSignalHandler(oldH);}}}

    在native code hand0里并沒有將handle的方法傳進去,只是傳了一個整型值。

    在c++代碼中hand0里調用了函數?JVM_RegisterSignal,具體來看一下這個函數的實現

    [cpp] view plaincopyprint?
  • JVM_ENTRY_NO_ENV(void*,?JVM_RegisterSignal(jint?sig,?void*?handler))??
  • ??//?Copied?from?classic?vm??
  • ??//?signals_md.c???????1.4?98/08/23??
  • ??void*?newHandler?=?handler?==?(void?*)2??
  • ?????????????????????os::user_handler()??
  • ???????????????????:?handler;??
  • ??switch?(sig)?{??
  • ????/*?The?following?are?already?used?by?the?VM.?*/??
  • ????case?INTERRUPT_SIGNAL:??
  • ????case?SIGFPE:??
  • ????case?SIGILL:??
  • ????case?SIGSEGV:??
  • ??
  • ????/*?The?following?signal?is?used?by?the?VM?to?dump?thread?stacks?unless?
  • ???????ReduceSignalUsage?is?set,?in?which?case?the?user?is?allowed?to?set?
  • ???????his?own?_native_?handler?for?this?signal;?thus,?in?either?case,?
  • ???????we?do?not?allow?JVM_RegisterSignal?to?change?the?handler.?*/??
  • ????case?BREAK_SIGNAL:??
  • ??????return?(void?*)-1;??
  • ??
  • ????/*?The?following?signals?are?used?for?Shutdown?Hooks?support.?However,?if?
  • ???????ReduceSignalUsage?(-Xrs)?is?set,?Shutdown?Hooks?must?be?invoked?via?
  • ???????System.exit(),?Java?is?not?allowed?to?use?these?signals,?and?the?the?
  • ???????user?is?allowed?to?set?his?own?_native_?handler?for?these?signals?and?
  • ???????invoke?System.exit()?as?needed.?Terminator.setup()?is?avoiding?
  • ???????registration?of?these?signals?when?-Xrs?is?present.?
  • ???????-?If?the?HUP?signal?is?ignored?(from?the?nohup)?command,?then?Java?
  • ?????????is?not?allowed?to?use?this?signal.?
  • ?????*/??
  • ??
  • ????case?SHUTDOWN1_SIGNAL:??
  • ????case?SHUTDOWN2_SIGNAL:??
  • ????case?SHUTDOWN3_SIGNAL:??
  • ??????if?(ReduceSignalUsage)?return?(void*)-1;??
  • ??????if?(os::Linux::is_sig_ignored(sig))?return?(void*)1;??
  • ??}??
  • ??
  • ??void*?oldHandler?=?os::signal(sig,?newHandler);??
  • ??if?(oldHandler?==?os::user_handler())?{??
  • ??????return?(void?*)2;??
  • ??}?else?{??
  • ??????return?oldHandler;??
  • ??}??
  • JVM_END??
  • JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler))// Copied from classic vm// signals_md.c 1.4 98/08/23void* newHandler = handler == (void *)2? os::user_handler(): handler;switch (sig) {/* The following are already used by the VM. */case INTERRUPT_SIGNAL:case SIGFPE:case SIGILL:case SIGSEGV:/* The following signal is used by the VM to dump thread stacks unlessReduceSignalUsage is set, in which case the user is allowed to sethis own _native_ handler for this signal; thus, in either case,we do not allow JVM_RegisterSignal to change the handler. */case BREAK_SIGNAL:return (void *)-1;/* The following signals are used for Shutdown Hooks support. However, ifReduceSignalUsage (-Xrs) is set, Shutdown Hooks must be invoked viaSystem.exit(), Java is not allowed to use these signals, and the theuser is allowed to set his own _native_ handler for these signals andinvoke System.exit() as needed. Terminator.setup() is avoidingregistration of these signals when -Xrs is present.- If the HUP signal is ignored (from the nohup) command, then Javais not allowed to use this signal.*/case SHUTDOWN1_SIGNAL:case SHUTDOWN2_SIGNAL:case SHUTDOWN3_SIGNAL:if (ReduceSignalUsage) return (void*)-1;if (os::Linux::is_sig_ignored(sig)) return (void*)1;}void* oldHandler = os::signal(sig, newHandler);if (oldHandler == os::user_handler()) {return (void *)2;} else {return oldHandler;} JVM_END


    [cpp] view plaincopyprint?
  • void*?newHandler?=?handler?==?(void?*)2??
  • ?????????????????????os::user_handler()??
  • ???????????????????:?handler;??
  • void* newHandler = handler == (void *)2? os::user_handler(): handler;

    因為傳進的值是2,那么真正在c++里的信號處理函數實際上os::user_handler(),同時jvm也保護了幾個信號,不允許外部改變信號的處理函數。

    一切豁然開朗,筆者的博客(java 中關于信號的處理在linux下的實現)已經提到過這個函數,通過os:signal_notify 去通知signal dispatcher 線程的os::signal_wait,也就是接受到信號的線程通過信號函數notify到處理信號的線程(signal dispatcher ),最后由該線程做后續的事情。

    具體來看signal dispatcher 的thread entry

    [cpp] view plaincopyprint?
  • static?void?signal_thread_entry(JavaThread*?thread,?TRAPS)?{??
  • ??????....??
  • ??????default:?{??
  • ????????//?Dispatch?the?signal?to?java??
  • ????????HandleMark?hm(THREAD);??
  • ????????klassOop?k?=?SystemDictionary::resolve_or_null(vmSymbolHandles::sun_misc_Signal(),?THREAD);??
  • ????????KlassHandle?klass?(THREAD,?k);??
  • ????????if?(klass.not_null())?{??
  • ??????????JavaValue?result(T_VOID);??
  • ??????????JavaCallArguments?args;??
  • ??????????args.push_int(sig);??
  • ??????????JavaCalls::call_static(??
  • ????????????&result,??
  • ????????????klass,??
  • ????????????vmSymbolHandles::dispatch_name(),??
  • ????????????vmSymbolHandles::int_void_signature(),??
  • ????????????&args,??
  • ????????????THREAD??
  • ??????????);??
  • ????????}??
  • ????????....??
  • }??
  • static void signal_thread_entry(JavaThread* thread, TRAPS) {....default: {// Dispatch the signal to javaHandleMark hm(THREAD);klassOop k = SystemDictionary::resolve_or_null(vmSymbolHandles::sun_misc_Signal(), THREAD);KlassHandle klass (THREAD, k);if (klass.not_null()) {JavaValue result(T_VOID);JavaCallArguments args;args.push_int(sig);JavaCalls::call_static(&result,klass,vmSymbolHandles::dispatch_name(),vmSymbolHandles::int_void_signature(),&args,THREAD);}.... }


    也就是在jvm的c++源碼中,反調用了java的方法,也就是signal.java中的dispatch(int number),方法dispatch中才是真正的調用了在文章開頭提到的注冊到Signal的方法handle。

    dispatch方法中仍然起了一個新的線程去處理handle,這樣就不會block?signal dispatcher 線程。

    總結

    以上是生活随笔為你收集整理的Java Signal实例的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。