日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
PlayFrameworkhotswap及源碼分析

play! ***的賣點就在于 hot swap,正如它自己宣稱的:

創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的新蔡網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

reach your maximum productivity。play! 允許開發(fā)人員修改java文件,保存,然后刷新瀏覽器,立馬可以看到效果。不需要編譯,也不需要重啟服務(wù)器。

Java 要想實現(xiàn)動態(tài)更新 class 文件,不外乎兩種手段:替換 classloader、替換 JVM。因為替換 JVM 引起的開銷更大,需要維護 JVM 的堆、棧等運行信息,所以 hot swap 通常是選擇替換 classloader。比如 grails 里面就是選擇替換 classloader,它會自己維護一個線程,定期輪詢源文件是否發(fā)生修改,以替換原來的 classloader。那么 play! 宣稱的 hot swap 又是怎么實現(xiàn)的呢?

讓我們來看看play! 的內(nèi)部流程:

1. play! 使用了 Apache Mina 作為底層的 http server,然后使用了自己關(guān)于 Mina IoHandler 接口的實現(xiàn)—— HttpHandler

2. 當瀏覽器發(fā)起一個 request:

2.1 Mina Server 生成一個 Mina Request,轉(zhuǎn)發(fā)給 HttpHandler 的 messageReceived 方法

2.2 play! 解析 Mina Request 和 Mina Session,包裝成自己的 Request 對象

 
 
 
  1. Request request = parseRequest(minaRequest, session);

2.3 play! 檢測 Route 文件修改情況,根據(jù) Route 配置信息將 Route/Action 的信息賦給 Request 對象

 
 
 
  1. Router.detectChanges();
  2. Router.route(request);

2.4 play! 根據(jù)當前配置的開發(fā)模式來采用不同的策略調(diào)用 Action 來理 Request

 
 
 
  1. if (Play.mode == Play.Mode.DEV) {
  2. Invoker.invokeInThread(new MinaInvocation(session, minaRequest, minaResponse, request, response));
  3. } else {
  4. Invoker.invoke(new MinaInvocation(session, minaRequest, minaResponse, request, response));
  5. }

2.5 如果 play! 當前是 DEV 模式,invokeInThread方法會讓 invocation 對象代理 run() 方法

 
 
 
  1. public void run() {
  2. try {
  3. before();
  4. execute();
  5. after();
  6. } catch (Throwable e) {
  7. onException(e);
  8. } finally {
  9. _finally();
  10. }
  11. }

咱們來看看 before() 方法:

 
 
 
  1. public static void before() {
  2. Thread.currentThread().setContextClassLoader(Play.classloader);
  3. if(!Play.id.equals("test")) {
  4. Play.detectChanges();
  5. if (!Play.started) {
  6. Play.start();
  7. }
  8. }
  9. //
  10. }

在 Play 類的 detectChanges() 方法里面,有這么一句:

 
 
 
  1. classloader.detectChanges();

哈哈,play! 修改源文件后,刷新瀏覽器即見效的奧秘就在這里了。再進去看看 play! 自定義 classloader 的 detectChanges() 方法:

 
 
 
  1. public void detectChanges() {
  2. // Now check for file modification
  3. List modifieds = new ArrayList();
  4. for (ApplicationClass applicationClass : Play.classes.all()) {
  5. if (applicationClass.timestamp < applicationClass.javaFile.lastModified()) {
  6. applicationClass.refresh();
  7. modifieds.add(applicationClass);
  8. }
  9. }
  10. List newDefinitions = new ArrayList();
  11. Map annotationsHashes = new HashMap();
  12. for (ApplicationClass applicationClass : modifieds) {
  13. annotationsHashes.put(applicationClass.javaClass, computeAnnotationsHash(applicationClass.javaClass));
  14. if (applicationClass.compile() == null) {
  15. Play.classes.classes.remove(applicationClass.name);
  16. } else {
  17. applicationClass.enhance();
  18. BytecodeCache.cacheBytecode(applicationClass.enhancedByteCode, applicationClass.name, applicationClass.javaSource);
  19. newDefinitions.add(new ClassDefinition(applicationClass.javaClass, applicationClass.enhancedByteCode));
  20. }
  21. }
  22. try {
  23. HotswapAgent.reload(newDefinitions.toArray(new ClassDefinition[newDefinitions.size()]));
  24. } catch (ClassNotFoundException e) {
  25. throw new UnexpectedException(e);
  26. } catch (UnmodifiableClassException e) {
  27. throw new UnexpectedException(e);
  28. }
  29. // Check new annotations
  30. for (Class clazz : annotationsHashes.keySet()) {
  31. if (annotationsHashes.get(clazz) != computeAnnotationsHash(clazz)) {
  32. throw new RuntimeException("Annotations change !");
  33. }
  34. }
  35. // Now check if there is new classes or removed classes
  36. int hash = computePathHash();
  37. if (hash != this.pathHash) {
  38. // Remove class for deleted files !!
  39. for (ApplicationClass applicationClass : Play.classes.all()) {
  40. if (!applicationClass.javaFile.exists()) {
  41. Play.classes.classes.remove(applicationClass.name);
  42. }
  43. if(applicationClass.name.contains("$")) {
  44. Play.classes.classes.remove(applicationClass.name);
  45. }
  46. }
  47. throw new RuntimeException("Path has changed");
  48. }
  49. }

HotswapAgent類的 reload 方法如下:

 
 
 
  1. public static void reload(ClassDefinition definitions) throws UnmodifiableClassException, ClassNotFoundException {
  2. instrumentation.redefineClasses(definitions);
  3. }

讀到這里,也就弄清楚了 play! 怎么實現(xiàn) hot swap 的原理了,還是調(diào)用java.lang.instrument目錄下的類和方法來實現(xiàn)的 hot swap。不存在魔法,play! 還是選擇了替換 classloader,只不過這個替換動作發(fā)生在處理 http request 的時候,于是開發(fā)人員用起來就是“刷新瀏覽器就可以看見效果了”。


當前標題:PlayFrameworkhotswap及源碼分析
鏈接地址:http://m.5511xx.com/article/dhdopoi.html