`

从jvm的自愈说起-设计JVM的疯子和写java程序的疯子

阅读更多

 

http://it.deepinmind.com/jvm/2014/12/15/self-healing-jvm.html这里说了一个观点,叫做 JVM的自愈能力,就是说JVM在遇到问题时会自己发现问题解决问题,举例如下:

 

 

package eu.plumbr.test;

public class HealMe {
  private static final int SIZE = (int) (Runtime.getRuntime().maxMemory() * 0.6);

  public static void main(String[] args) throws Exception {
    for (int i = 0; i < 1000; i++) {
      allocateMemory(i);
    }
  }

  private static void allocateMemory(int i) {
    try {
      {
        byte[] bytes = new byte[SIZE];
        System.out.println(bytes.length);
      }

      byte[] moreBytes = new byte[SIZE];
      System.out.println(moreBytes.length);

      System.out.println("I allocated memory successfully " + i);

    } catch (OutOfMemoryError e) {
      System.out.println("I failed to allocate memory " + i);
    }
  }
}

按照道理,总是这样分配内存一定会内存不足,报OOM异常的,但是,文章提到,在JVM8中,在运行了256次allocateMemory()方法2之后,C1编译器会将这个方法进行3级编译。它会一次性查看整个方法,因此它能推断出后面不会再用到bytes变量,可以对它进行GC。所以才会触发垃圾回收,因此程序才能奇迹般地自愈。

 

我想说的是:设计这样JVM的人和在真正产品实现里写这样代码的人都是疯子。


前者是越俎代庖,非要管人家上层程序员的事:你就是一个VM,一个底层,上层要你干啥你就干啥,自作主张的给人家优化---就行秘书自作主张的改领导的批示一样。结果又两个,一是改了不大紧要的地方,可有可无,真正重要的地方改不了;二是改了让人家的业务过程变了,与预期不符。是在可笑之极。

---一句话:谁的逻辑除了bug谁负责,这还需要解释吗?家里养的猫不抓老鼠,就指望养的牛抓老鼠?

后者是疯子:你写个代码出这样的bug,自己找根绳去吧!有了bug自己不负责,指望jvm来怎么治愈自己,说实在的也就是写个程序玩玩吧,真正写商业程序,死都不知道死到哪儿去。

 

 

 

 

 

2
10
分享到:
评论
11 楼 windshome 2014-12-19  
其实这属于开发方法论,在设计时需要仔细设计的一点。

完整系统切割为多个子系统(定义各子系统的职责和通信、依赖关系、层次关系),一个子系统切割为模块(模块职责和通信、依赖关系),一个模块划分为多个部件(部件职责和通信、依赖关系)。

从另外一个角度,还可以划分为框架(例如IoC框架)、基础设施(例如JVM,或者数据库连接池、界面组件)处理单元(业务处理),各部分在整体系统中,各有各的职责,做好自己本分,按照设计做好通信和依赖的接口,系统基本就能很好的连接在一起运转,不需要哪个部分非要管别的部分的事情。也不要指望自己的事情由其他模块代替来做。哪个部分出了问题,哪个部分负责。


还有一种情况,就是负责某一部分的人是懒虫,巴不得其它部分能替自己做一些,于是臃肿的框架出现了,复杂的底层设施日趋复杂,业务除了所谓的CRUD就没啥东西了,也号称自己业务逻辑....短期看,项目型开发来看,还挺快,但长期来看,从开发产品的角度看,损害了设计,损害了系统设计开发中人的行为模式。

10 楼 windshome 2014-12-18  
ljbupc 写道
windshome 写道
其实这是自作聪明。呵呵。

一个平台,忠实的做上层交待的事情就可以了,水平高的人做出水平高且好用的东西,水平差的人做的东西就是总是出bug。平台没有必要管这个。





理解你的意思,但事实上,水平高的没几个,水平差的很多(包括我)。

jrokit 应该很早就加入了这个东东的,而且我应该遇到过这个东西引起的倒霉事。
一个批量程序,用jrokit1.6运行,前几百条记录执行的计算结果是正确的,后面的结果就变成0了;
换成sun jdk1.6就没有该问题。

后来换sun jdk了,没有时间去仔细研究,不过从现象来看,99%的可能性是jrokit自己帮我“优化”程序了。


水平什么样都没有关系,自己出问题了自己负责就行。
9 楼 ljbupc 2014-12-18  
我勒过去。。。。
刚去测验了一下。。
这程序在jrokit 1.6中一开始就是分配成功的。。。。
8 楼 ljbupc 2014-12-18  
windshome 写道
其实这是自作聪明。呵呵。

一个平台,忠实的做上层交待的事情就可以了,水平高的人做出水平高且好用的东西,水平差的人做的东西就是总是出bug。平台没有必要管这个。





理解你的意思,但事实上,水平高的没几个,水平差的很多(包括我)。

jrokit 应该很早就加入了这个东东的,而且我应该遇到过这个东西引起的倒霉事。
一个批量程序,用jrokit1.6运行,前几百条记录执行的计算结果是正确的,后面的结果就变成0了;
换成sun jdk1.6就没有该问题。

后来换sun jdk了,没有时间去仔细研究,不过从现象来看,99%的可能性是jrokit自己帮我“优化”程序了。
7 楼 mike.liu 2014-12-18  
其实说得也有一定道理。
职责不分,功能太臃肿,是导致Android用2倍内存也拼不过iPhone顺畅的原因之一。
在iOS里面,内存分配和释放,框架做一部分,程序员负责一部分,各自做好自己的事情,没有GC。JVM帮助程序员管理了所有内存分配和释放的事情,是必须付出代价的。高内存占用和间歇性的卡顿,就是代价之一。
系统设计的策略就是取舍,保守未必是坏事,激进未必是好事,仔细权衡之后,看运气吧。
6 楼 windshome 2014-12-18  
其实这是自作聪明。呵呵。

一个平台,忠实的做上层交待的事情就可以了,水平高的人做出水平高且好用的东西,水平差的人做的东西就是总是出bug。平台没有必要管这个。



5 楼 ljbupc 2014-12-18  
windshome 写道
ljbupc 写道
其实博主不必要这么激动,
JVM也是一个虚拟机,这么设计么就是为了避免一两个恶意程序让整个虚拟机宕机;
JVM为了不让自己宕机,找到一些没有再使用过的东西快速回收掉。
其实linux也有类似的设计,当需要内存而没有内存的时候,内核还会kill掉某些进程。

不过这样的设计就要求较高,回收资源可以,但不能乱去优化,改变应用程序的处理逻辑。那样就容易出现优化错误出现一些奇奇怪怪的bug。


呵呵,我只是说有些职责不明,业务端设计实现存在bug,导致JVM宕机,是人家的事情,和你jvm有什么关系?jvm只是一个支撑业务的基础设施,上层使用不当,出现问题就应该负相应的责任,想办法去处理。


其实这也是一个卖点,他多了一层保护。
复杂程序都会有bug的,他说他能减少bug带来的影响,相信很多公司都会觉得好(毕竟大部分写程序的人水平不一定有多高),当然前提是成熟。

运行时编译优化是为了提高代码运行效率,干了内存泄露回收的事只是个附带。
4 楼 windshome 2014-12-18  
ljbupc 写道
其实博主不必要这么激动,
JVM也是一个虚拟机,这么设计么就是为了避免一两个恶意程序让整个虚拟机宕机;
JVM为了不让自己宕机,找到一些没有再使用过的东西快速回收掉。
其实linux也有类似的设计,当需要内存而没有内存的时候,内核还会kill掉某些进程。

不过这样的设计就要求较高,回收资源可以,但不能乱去优化,改变应用程序的处理逻辑。那样就容易出现优化错误出现一些奇奇怪怪的bug。


呵呵,我只是说有些职责不明,业务端设计实现存在bug,导致JVM宕机,是人家的事情,和你jvm有什么关系?jvm只是一个支撑业务的基础设施,上层使用不当,出现问题就应该负相应的责任,想办法去处理。
3 楼 wu.sheng 2014-12-18  
JVM的优化目的,应该是减少无用的垃圾变量的声明和使用,局部变量的尽快回收,只是刚巧达到了这么一个效果而已。
2 楼 fxldiezh 2014-12-18  
JVM越来越傻瓜化了
1 楼 ljbupc 2014-12-18  
其实博主不必要这么激动,
JVM也是一个虚拟机,这么设计么就是为了避免一两个恶意程序让整个虚拟机宕机;
JVM为了不让自己宕机,找到一些没有再使用过的东西快速回收掉。
其实linux也有类似的设计,当需要内存而没有内存的时候,内核还会kill掉某些进程。

不过这样的设计就要求较高,回收资源可以,但不能乱去优化,改变应用程序的处理逻辑。那样就容易出现优化错误出现一些奇奇怪怪的bug。

相关推荐

    Excel模板 Java程序设计基础教程-完整教案.docx

    ### Java程序设计基础教程知识点详述 #### 一、Java语言概述 - **Java语言的起源与发展** - **诞生背景**:Java语言由Sun Microsystems公司于1995年推出,最初是作为Oak项目的一部分开始研发。Oak项目旨在开发一...

    java面试题库

    Java学习笔记中可能包含了对Java语言的深入理解和实践技巧,包括设计模式、并发编程、JVM内存模型、垃圾收集机制、性能优化等方面。这些知识能帮助你在实际项目中写出高效、可维护的代码。 面试题类型通常包括但不...

    java开发的计算器

    通过研究这个Java计算器项目,开发者不仅可以了解基础的Java编程,还可以深入学习GUI设计、事件处理和异常管理等进阶主题,对于提升Java编程技能大有裨益。同时,对于初学者来说,这是一个很好的实践项目,因为它...

    学习java需要的一些中文帮助文档

    7. **JDK(Java Development Kit)**:它是Java开发的基础,包含了编译器、JVM(Java虚拟机)和各种工具。熟悉JDK的使用和配置,能帮助开发者编写、运行和调试Java程序。 8. **jQuery**:这是一个轻量级的...

    jdk-7u71-windows-i586[32位]

    JDK(Java Development Kit)是Java语言的核心开发工具包,包含了Java运行环境(JRE)、Java虚拟机(JVM)、Java编译器、Java类库等核心组件。JDK 1.7(即Java SE 7)是Oracle公司发布的一个重要版本,于2011年7月28...

    idea 环境变量配置

    这些参数主要影响IDEA自身的启动和运行过程,也会影响到部署在IDEA上的应用程序的性能。例如,在描述部分提到的`-Xms256m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m`就是典型的JVM参数配置。 - **-Xms256m...

    redis资源包-没积分的关注私信我

    在Java开发中,Redis是常用的后端数据存储解决方案之一,因此了解Redis的基本概念、操作和与Java的交互方式至关重要。 Redis支持的数据结构包括字符串(Strings)、哈希(Hashes)、列表(Lists)、集合(Sets)和...

    开发环境战神.zip

    JDK提供了编译Java源代码所需的javac编译器,以及运行Java程序的Java虚拟机(JVM)。开发者还需要JRE(Java Runtime Environment),这是运行Java应用程序所必需的基础组件。 在压缩包内,"开发环境战神"可能包括一...

    如何将jar包打成可执行文件

    在Java编程环境中,将一个.jar(Java Archive)文件转换为可执行文件,通常是将它封装成Windows下的.exe可执行程序,以便非Java开发者也能轻松运行。这个过程涉及到几个关键步骤和工具,以下是一个详细的教程: 1. ...

    ssh2错误学习记录

    SSH(Secure Shell)是一种网络协议,用于在不安全的网络环境中提供安全的远程登录和其他服务。在本文中,我们将深入探讨SSH2错误的学习记录,主要包括以下几个方面: 1. **@Autowired注解问题**: `@Autowired`是...

    clipbot:一个用 clojure 编写的简单的可扩展 irchipchatslack bot

    "Clojure" 是一种基于 Lisp 的现代函数式编程语言,它运行在 Java 虚拟机(JVM)上,拥有强大的并发处理能力和简洁的语法。由于 "clipbot" 使用 Clojure 开发,我们可以推断出该机器人利用了 Clojure 的这些优势,...

Global site tag (gtag.js) - Google Analytics