intellij-idea-2016 - intellij idea热部署怎么也这么弱呢?

查看:143
本文介绍了intellij-idea-2016 - intellij idea热部署怎么也这么弱呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

最近在使用Intellij idea, 本以为它的热部署功能应该很强大, 没想到和Eclipse差不多, 下面的变化均不支持自动加载, 均需重启。

  • 类中增加增加setter/getter方法 不支持

  • 更改类中的变量类型(如String -> long) 不支持

  • 更改url 不支持
    如@RequestMapping(value = "/foo") --> @RequestMapping(value = "/bar")

热部署真的有这么复杂吗? 连商业软件都做不到?

解决方案

这是Java作为编译型语言的硬伤,避无可避的生死劫.

下面转一些语言的热部署对比:

在 Java 开发领域,热部署一直是一个难以解决的问题,目前的 Java 虚拟机只能实现方法体的修改热部署, 对于整个类的结构修改,仍然需要重启虚拟机,对类重新加载才能完成更新操作。 而PHP在开发时就友好多了,修改代码立即生效。 在生产环境运行时,开启了OPcache,只要设定了opcache.revalidate_freq=60,在60秒后修改的代码同样会自动生效。

热部署/热插拔(HotSwap)是在不重启 Java 虚拟机的前提下,能自动侦测到 class 文件的变化,更新运行时 class 的行为。 Java 类是通过 Java 虚拟机加载的,某个类的 class 文件在被 classloader 加载后,会生成对应的 Class 对象,之后就可以创建该类的实例。 默认的虚拟机行为只会在启动时加载类,如果后期有一个类需要更新的话,单纯替换编译的 class 文件,Java 虚拟机是不会更新正在运行的 class。 如果要实现热部署,最根本的方式是修改虚拟机的源代码,改变 classloader 的加载行为,使虚拟机能监听 class 文件的更新,重新加载 class 文件, 这样的行为破坏性很大,为后续的 JVM 升级埋下了一个大坑。

在进行Java Web程序开发过程中,经常遇到这种问题,修改一个java文件(*.java),需要重启Web服务器(如Tomcat等),部署项目。而重启服务浪费了大量的时间。在小项目中,也许我们感觉不到。但对于大型项目:如数据中心,生产等系统开发而言,往往起/停需要等待几分钟时间。更浪费时间的是,对于一个类中的方法的调试过程,如果修改多次,Tomcat需要反复重载容器,那么浪费的时间更多。

使用过Hibernate, Spring或其他大型组件,写过50个类以上的Web应用程序的开发者应该知道,当系统中有很多类时,如果开启了Tomcat的reloadable=true,那么每当相关文件改变时,Tomcat会停止Web应用并释放内存,然后重新加载Web应用,这实在是个浩大的工程。

配置Tomcat不因为类的修改重新加载容器,如果你只是修改了类的实现(方法体内的代码),而不是添加或删除类的方法和成员变量, 不需要重启Tomcat,代码就能生效,因为class被更新了,以后新建的instance自然跟着更新. 不过Java中旧的驻留在内存的instance个人认为不会得到更新.而PHP则不存在这些问题,因为每次请求完成,即释放所有资源. 如果PHP文件没有改变,操作系统将会从磁盘缓存(内存)里读取数据并响应新的请求.

Tomcat设置reloadable="true"后,会监视在WEB-INF/classes和WEB-INF/lib目录class文件的改动.如果监视到有class文件被更新,Tomcat会重新加载整个Web应用,当项目庞大时,重载的类(包括框架)就非常多,重载时间就会变长,因此造成服务中断,自然也就谈不上"热部署".Tomcat的reloadable="true"只建议在开发环境中使用,切勿生产环境.

编写类->编译类->Tomcat重载整个项目的类(项目庞大,类非常多,包括框架)->服务中断->无法热部署

JRebel是一款商业付费的JVM插件,它使得JAVAer能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响. JRebel使你能即时分别看到代码,类和资源的变化,你可以一个个上传而不是一次性全部部署. 当程序员在开发环境中对任何一个类或者资源作出修改的时候,这个变化会直接反应在部署好的应用程序上, 从而跳过了构建和部署的过程.

Erlang的代码热更新实现:
Erlang的代码加载由一个名为code_server的模块管理,除了启动时的一些必要代码外,大部分的代码均由code_server加载. 当code_server发现模块代码被更新后,会重新加载模块,此后的新请求会使用新模块执行,而原有还在执行的请求则继续使用老模块执行. 老模块会在新模块加载后,被打上old标签,新模块则是current标签. Erlang中并非所有代码均允许热更新,如kernel,stdlib,compiler等基础模块默认是不允许更新的.

如果你有 PHP 开发经验,会习惯在修改 PHP 脚本后直接刷新浏览器以观察结果, 而你在开发 Node.JS 实现的 HTTP 应用时会发现,无论你修改了代码的哪一部份,都必须终止Node.JS 再重新运行才会奏效。 这是因为 Node.JS 只有在第一次引用到某部份时才会去解析脚本文件,以后都会直接访问内存,避免重复载入, 而 PHP 则总是重新读取并解析脚本(如果没有开启ZendOpcache)。 Node.JS的这种设计虽然有利于提高性能,却不利于开发调试, 因为我们在开发过程中总是希望修改后立即看到效果,而不是每次都要终止进程并重启。 正常情况下,若你修改了js文件,或是调试功能,或是增加功能。
这时需要重新发布该服务,每次修改都需要执行以下两步:
1.Ctrl+C
2.node server.js
node.js应用的热部署需要额外的工具,比如nodemon.
另外 node-dev 模块是一个开发工具,当你的 js 文件修改保存后,
它会自动重启服务进程,嫌 Ctrl + C / Up / Down 费劲的同学可以尝试用它减轻开发调试的烦恼。

这篇关于intellij-idea-2016 - intellij idea热部署怎么也这么弱呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆