`
longgangbai
  • 浏览: 7251178 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

Java的垃圾回收机制(转)  

一。谁在做Garbage Collection?

 
    一种流行的说法:在C++里,是系统在做垃圾回收;而在Java里,是java自身在做。
 
    在C++里,释放内存是手动处理的,要用delete运算符来释放分配的内存。这是流行的说法。确切地说,是应用认为不需要某实体时,就需用 delete告诉系统,可以回收这块空间了。这个要求,对编码者来说,是件很麻烦、很难做到的事。随便上哪个BBS,在C/C++版块里总是有一大堆关于 内存泄漏的话题。
 
    java采用一种不同的,很方便的方法:Garbage Collection.垃圾回收机制放在JVM里。jvm完全负责垃圾回收事宜,应用只在需要时申请空间,而在抛弃对象时不必关心空间回收问题。
 
    二。对象在啥时被丢弃?
 
    在C++里,当对象离开其作用域时,该对象即被应用抛弃。
 
    是对象的生命期不再与其作用域有关,而仅仅与引用有关。
 
    java的垃圾回收机制一般包含近十种算法。对这些算法中的多数,我们不必予以关心。只有其中最简单的一个:引用计数法,与编码有关。
 
    一个对象,可以有一个或多个引用变量指向它。当一个对象不再有任何一个引用变量指向它时,这个对象就被应用抛弃了。或者说,这个对象可以被垃圾回收机制回收了。
 
    这就是说,当不存在对某对象的任何引用时,就意味着,应用告诉jvm:我不要这个对象,你可以回收了。
 
    jvm的垃圾回收机制对堆空间做实时检测。当发现某对象的引用计数为0时,就将该对象列入待回收列表中。但是,并不是马上予以销毁。
 
    三。丢弃就被回收?
 
    该对象被认定为没有存在的必要了,那么它所占用的内存就可以被释放。被回收的内存可以用于后续的再分配。
 
    但是,并不是对象被抛弃后当即被回收的。jvm进程做空间回收有较大的系统开销。如果每当某应用进程丢弃一个对象,就立即回收它的空间,势必会使整个系统的运转效率非常低下。
 
    前面说过,JVM的垃圾回收机制有多个算法。除了引用计数法是用来判断对象是否已被抛弃外,其它算法是用来确定何时及如何做回收。jvm的垃圾回收机制要在时间和空间之间做个平衡。
 
    因此,为了提高系统效率,垃圾回收器通常只在满足两个条件时才运行:即有对象要回收且系统需要回收。切记垃圾回收要占用时间,因此,java运行时系统只在需要的时候才使用它。因此你无法知道垃圾回收发生的精确时间。
 
    四。没有引用变量指向的对象有用吗?
 
    前面说了,没挂上引用变量的对象是被应用丢弃的,这意味着,它在堆空间里是个垃圾,随时可能被jvm回收。
 
    不过,这里有个不是例外的例外。对于一次性使用的对象(有些书称之为临时对象),可以不用引用变量指向它。举个最简单也最常见的例子:
 
    System.out.println(“I am java!”);
 
    就是创建了一个字符串对象后,直接传递给println()方法。
 
    五。应用能干预垃圾回收吗?
 
    许多人对Java的垃圾回收不放心,希望在应用代码里控制JVM的垃圾回收运作。这是不可能的事。对垃圾回收机制来说,应用只有两个途径发消息给 JVM.第一个前面已经说了,就是将指向某对象的所有引用变量全部移走。这就相当于向jvm发了一个消息:这个对象不要了。第二个是调用库方法 System.gc(),多数书里说调用它让java做垃圾回收。
 
    第一个是一个告知,而调用System.gc()也仅仅是一个请求。jvm接受这个消息后,并不是立即做垃圾回收,而只是对几个垃圾回收算法做了加权,使垃圾回收操作容易发生,或提早发生,或回收较多而已。
 
    希望jvm及时回收垃圾,是一种需求。其实,还有相反的一种需要:在某段时间内最好不要回收垃圾。要求运行速度最快的实时系统,特别是嵌入式系统,往往希望如此。
 
    Java的垃圾回收机制是为所有java应用进程服务的,而不是为某个特定的进程服务的。因此,任何一个进程都不能命令垃圾回收机制做什么、怎么做或做多少。
 
    六。对象被回收时要做的事
 
    一个对象在运行时,可能会有一些东西与其关连。因此,当对象即将被销毁时,有时需要做一些善后工作。可以把这些操作写在finalize()方法(常称之为终止器)里。
 
    protected void finalize()
 
    {
 
    // finalization code here
 
    }
 
    这个终止器的用途类似于C++里的析构函数,而且都是自动调用的。但是,两者的调用时机不一样,使两者的表现行为有重大区别。C++的析构函数总是当对 象离开作用域时被调用。这就是说,C++析构函数的调用时机是确定的,且是可被应用判知的。但是,java终止器却是在对象被销毁时。由上所知,被丢弃的 对象何时被销毁,应用是无法获知的。而且,对于大多数场合,被丢弃对象在应用终止后仍未销毁。
 
    在编码时,考虑到这一点。譬如,某对象在运作时打开了某个文件,在对象被丢弃时不关闭它,而是把文件关闭语句写在终止器里。这样做对文件操作会造成问 题。如果文件是独占打开的,则其它对象将无法访问这个文件。如果文件是共享打开的,则另一访问该文件的对象直至应用终结仍不能读到被丢弃对象写入该文件的 新内容。
 
    至少对于文件操作,编码者应认清java终止器与C++析构函数之间的差异。
 
    那么,当应用终止,会不会执行应用中的所有finalize()呢?据Bruce Eckel在Thinking in java里的观点:“到程序结束的时候,并非所有收尾模块都会得到调用”。这还仅仅是指应用正常终止的场合,非正常终止呢?
 
    因此,哪些收尾操作可以放在finalize()里,是需要酌酎的。

 

来自:http://flynewton.blog.163.com/blog/static/12693071320098112220157/

前段时间一直在运用memcached来保存session的集群方案,这的确是实现HA和HP的一个好方案。但是在实现上还存在不少的bug。我和大家分享另外一种HA方案:JVM堆级群集。

JVM-level clustering主要是通过terracotta来实现,terracotta在2003年成立,代码是最近才开源的,license对企业也没有太 大的限制,据相关的报道,terracotta正努力劝服sun,让JVM-level clustering成为标准,嵌入到JDK中。然后它的企业版应用主要是靠服务攒钱,它的战略有点象Redhat。在这里我先介绍一下 Terracotta

Terracotta到底是什么呢?官方是这样定义的:Open Terracotta is an enterprise-class, open-source, JVM-level clustering solution. JVM-level clustering simplifies enterprise Java by enabling applications to be deployed on multiple JVMs, yet interact with each other as if they were running on the same JVM. Terracotta extends the Java Memory Model of a single JVM to include a cluster of virtual machines such that threads on one virtual machine can interact with threads on another virtual machine as if they were all on the same virtual machine with an unlimited amount of heap.

 Terracotta实现了什么?

1)  堆级的复制:集群时需要拷贝的对象在堆之间进行

2)  超大的虚拟堆:由于是JVM层次的集群,所以堆要比单个JVM大很多

3)  多种集群锁语法:distributed wait/notify and synchronized

4)  运行实时监控

5)  无需序列化实现集群

6)  Find-Grained Changes:由于集群时,terracotta不要求序列化,所以对象拷贝可以细化到对象中的每一个field,就是说在进行replication 的时候,当对象发生变化的时候,不需要整个对象进行拷贝,只需要拷贝发生变化的那个field。P.s.这点也是我最喜欢的,这对于性能的提高会有明显的 效果

 

Terracotta能给我们做什么?(这个很简单,我也不做翻译了)

  • HTTP Session Replication - Tomcat, Weblogic, Websphere
  • Distributed Cache - from java.util.Hashmap to OSCache, we support it,
  • Work/Manager Distributed Queries - Coordination is easy with Terracotta. We even have code to get you started on the Terracotta Forge
  • POJO Clustering/Spring integration- Everything from Spring Beans to java.util.HashMap
  • Collaboration/Coordination - Use a queue, use distributed wait/notify, or even Cyclic Barrier (We love Cycle Barrier ) with Terracotta coordination across VMs is as easy as coordination across threads

p.s. tomcat现在支持的版本有5.0,5.5,6.0;weblogic官方测试过的只有8.1,websphere只支持CE,6.1预计会在今年夏季测试完成,估计就是最近,如今还支持Lucence和Wicket的集群。具体可以查看他的官方网站

如果实习AOP的人应该对Terracotta的工作原理很容易理解。Terracotta一个很重要的概念是bytecode instrumentation,这种对字节流监控的技术在很多AOP的项目中都用到,例如AspectJ,AspectWerkz。

Terrocotta的介绍到此为止。

作为一个HA方案的设计者,在运用一项新技术的时候必须评估它给现有项目带来的风险,特别是terrcotta还没有足够的成熟。

1)               如果运用了terracotta,我们现有的项目需要有哪些方面的修改,这点我估计也是大家最关心的。由于terracotta运用了bytecode instrumentation的技术,所以我们现有的项目基本上不需要做任何修改。Terracotta提供一个配置文件tc-config.xml, 我们只需要在这个配置文件里配置一些必须参数就可以实现集群(p.s.官方提供了pojo,spring,tomcat,weblogic的预配置模版; 这点比用memcached来保存session要简单,而且考虑的问题要少,毕竟官方就支持用terracotta来管理session)。我现在的项 目是在tomcat下跑,需要做集群,众所周知,tomcat集群的replication性能是非常非常低的,但是如果运用sticky模式的话就不能 完全实现failuer-over。在这个时候terracotta就解决了这个问题,我用terracotta来管理我的session,由于它不需要 序列话和它find grained changes的机制,所以不存在大对象拷贝的问题,例如我有十个点,其中一个点发生了变化,它不会立刻把变化拷贝到所有点上,只会当某个点需要变化的时 候才把变化发送到该点上。我从一些监控工具里面发现,terracotta捕获了所有httpsession到terracotta的 sessiondata中,你会发现根本不存在httpsession,terracotta相当于一个代理,当httpsession getAttribute的时候,代理会从sessiondata中取到相对应的值,然后付给httpsession,具体的实现有兴趣的可以看看源代码

2)               性能的变化,把terracotta集成到项目后性能是否能有明显的提升?在官方文档中,对terracotta http session clustering和weblogic8.1 http session clustering做了一个比较(如果大家感兴趣的话,我可以以后配合实际再写篇有关terracotta方面性能测试的文章),结果让人比较让人惊讶

Measure

Gain from Terracotta

Throughput

67% increase in TPS

Memory Use

6-7 x reduction in garbage collection cycles

Latency

? 50% reduction

? Queue depth never exceeds 125, vs. 280-

560 for WebLogic

3)               Terracotta的扩展性。Terracotta是纯java编写的,源码开源,可以自己修改源代码进行扩展。而且terracotta很活跃,从它的策略来看,会有不错的发展和不久就会流行起来。

4)               从这点来看Terracotta相当一个中央服务器,那会不会terracotta出现single-point的问题呢?terracotta server本身支持集群

    好像写得太多了。说说我现在项目的HA方案吧,我正在实现和测试的方案是这样的:

Apache+5 tomcat+2 terrcotta server cluster+2 mysql cluster,在这个方案中还是存在单点问题,就是apache,我曾经考虑过用四层交换机来代替apache做balance

感兴趣的同学,欢迎对JVM-level Clustering和我的HA方案进行讨论

分享到:
评论

相关推荐

    性能调优文档_自动化测试

    该文档为在性能测试过程中对一些中间件的调优,如对tomcat的JVM、连接器、线程数等,中创中间件的JVM、连接数、日志级别调整,weblogic的JVM、关闭访问日志等。 同时包括数据库连接池的调优,Apache集群、oracle参数...

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    JVM级别 代码级别 分段优化 前端 web应用 服务应用 资源池 数据库 大数据与nosql zookeeper hadoop hbase mongodb strom spark java语言 语言语法基础 异常 泛型 内部类 反射 序列化 nIo ...

    大数据课程体系.pdf

    Java 基础 JAVA 开发基础知识 Eclipse 开发环境 多线程技术 Socket 网络技术 Regular Expression Java 反射技术 各种实战设计模式 面向对象设计原则详解 Java collection Reflection JVM 原理与配置、调优 Java 设计...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【*JVM】查看jvm虚拟机里面堆、线程的信息,你用过什么命令? 59 【JVM】垃圾回收算法有哪些? 59 引用计数法(Reference Counting Collector) 59 tracing算法(Tracing Collector) 61 compacting算法(Compacting ...

    阿里P7面试题整理集合

    乐观锁悲观锁等)、唯一索引和普通索 引的区别聊到了changeBuffer,聊了页分裂合页合并)比重较大 3)jvm调优(可达性分析算法中根节点有哪些、cms和G1区别、怎样GC调优、 怎样排查CPU彪高、内存彪高、逃逸分析) 4...

    大数据工程师学习计划.pdf

    但是写MapReduce需要Java代码量很⼤,所以出现了Hive,Pig等将SQL转 化成MapReduce的解析引擎; 普通的MapReduce处理数据只能⼀批⼀批地处理,时间延迟太长,为了实现每输⼊⼀条数据就能得到结果,于是出现了Storm/...

    open-muvr:muvr 的开源核心

    它是有弹性的:它的组件可以在适当的级别恢复,无论是单个角色、角色树还是整个 JVM。 它还使用事件溯源来确保即使是灾难性的故障和不可避免的错误也可以从中恢复。 它是响应式的:它不会阻塞,并且能够在整个集群...

    gemfire-log-scapper:该项目可以扫描 GemfireGeode 进程生成的所有日志文件,并创建一个 Excel 电子表格,其中仅包含指示问题的消息

    Gemfire 进程分布在多个成员之间,并且可能容易受到一个或多个单个成员的网络和 JVM 问题的影响。 在解决此类问题时,应检查每个 Gemfire 流程中的工件。 该工具有助于快速收集此类信息。 Gemfire 日志文件 每个 ...

    2017最新大数据架构师精英课程

    32_虚拟机内存结构-JVM-$ j; l* n7 g' u 33_代理模式 34_RDBMS 35_MySQL安装' `/ h# t# o# s& y1 \# ?* R5 f) p4 Z 36_MySQL常用命令-CRUD 37_java JDBC-insert 38_java JDBC-sql注入问题-preparedstatemnt 39_java ...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ Java面试题54.Spring事务的传播特性和隔离级别.mp4 │ Java面试题55.ORM是什么?ORM框架是什么?.mp4 │ Java面试题56.ibatis和hibernate有什么不同.mp4 │ Java面试题57.hibernate对象状态及其转换.mp4 │ Java...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    Spring.3.x企业应用开发实战(完整版).part2

    13.6.2 任务调度对应用程序集群的影响 13.6.3 任务调度云 13.6.4 Web应用程序中调度器的启动和关闭问题 13.7 小结 第14章 使用OXM进行对象XML映射 14.1 认识XML解析技术 14.1.1 什么是XML 14.1.2 XML的处理技术 14.2...

    Spring3.x企业应用开发实战(完整版) part1

    13.6.2 任务调度对应用程序集群的影响 13.6.3 任务调度云 13.6.4 Web应用程序中调度器的启动和关闭问题 13.7 小结 第14章 使用OXM进行对象XML映射 14.1 认识XML解析技术 14.1.1 什么是XML 14.1.2 XML的处理技术 14.2...

    java开源包1

    J2C 将 Java 代码转成 C++ 代码,这是源码级别的转换,输出的 C++ 代码是有效的代码。 OSGi 分布式通讯组件 R-OSGi R-OSGi 是一套适用于任意满足 OSGi 架构的分布式通讯组件。它以 jar 的形式发布,部署容易,使用...

    java开源包11

    J2C 将 Java 代码转成 C++ 代码,这是源码级别的转换,输出的 C++ 代码是有效的代码。 OSGi 分布式通讯组件 R-OSGi R-OSGi 是一套适用于任意满足 OSGi 架构的分布式通讯组件。它以 jar 的形式发布,部署容易,使用...

    java开源包2

    J2C 将 Java 代码转成 C++ 代码,这是源码级别的转换,输出的 C++ 代码是有效的代码。 OSGi 分布式通讯组件 R-OSGi R-OSGi 是一套适用于任意满足 OSGi 架构的分布式通讯组件。它以 jar 的形式发布,部署容易,使用...

Global site tag (gtag.js) - Google Analytics