仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 733|回复: 11
打印 上一主题 下一主题

[学习教程] JAVA网页编程之面向GC的Java编程仓酷云

[复制链接]
分手快乐 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:17:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
用winrar打包j2ee的程序和用IDE打包应用程序是一样的。按照你的想法,你是不是也希望服务器都整合由一家公司提供呢?Java程序员在编码过程当中一般不必要思索内存成绩,JVM经由高度优化的GC机制年夜部分情形下都可以很好地处置堆(Heap)的清算成绩。以致于很多Java程序员以为,我只必要体贴什么时候创立对象,而接纳对象,就交给GC来做吧!乃至有人说,假如在编程过程当中频仍思索内存成绩,是一种退步,这些事变应当交给编译器,交给假造机来办理。
这话实在也没有太年夜成绩,切实其实,年夜部分场景下体贴内存、GC的成绩,显得有点“庸人自扰”了,高老爷说过:
过早优化是万恶之源。
但另外一方面,甚么才是“过早优化”?
Ifwecoulddothingsrightforthefirsttime,whynot?
现实上JVM的内存模子(JMM)理应是Java程序员的基本常识,处置过几回JVM线上内存成绩以后就会很分明感觉到,良多体系成绩,都是内存成绩。
对JVM内存布局感乐趣的同砚能够看下浅析Java假造机布局与机制这篇文章,本文就不再赘述了,本文也其实不存眷详细的GC算法,相干的文章汗牛充栋,随时可查。
别的,不要期望GC优化的这些技能,能够对使用功能有成倍的进步,出格是对I/O麋集型的使用,或是实践落在YoungGC上的优化,大概效果只是帮你削减那末一点YoungGC的频次。
但我以为,优异程序员的代价,不在于其所把握的几招屠龙之术,而是在细节中见真著,就像后面说的,假如我们能够一次把事变做对,而且做好,在同意的局限内尽量寻求出色,为何不往做呢?
1、GC分代的基础假定

年夜部分GC算法,都将堆内存做分代(Generation)处置,可是为何要分代呢,又为何不叫内存分区、分段,而要用面向工夫、岁数的“代”来暗示分歧的内存地区?
GC分代的基础假定是:
尽年夜部分对象的性命周期都十分长久,存活工夫短。
而这些夭折的对象,恰好是GC算法必要起首存眷的。以是在年夜部分的GC中,YoungGC(也称作MinorGC)占了尽年夜部分,关于负载不高的使用,大概跑了数个月都不会产生FullGC。
基于这个条件,在编码过程当中,我们应当尽量地延长对象的性命周期。在已往,分派对象是一个对照重的操纵,以是有些程序员会尽量地削减new对象的次数,实验减小堆的分派开支,削减内存碎片。
可是,夭折对象的创立在JVM中比我们设想的功能更好,以是,不要小气new关头字,勇敢地往new吧。
固然条件是不做无谓的创立,对象创立的速度越高,那末GC也会越快被触发。
结论:


  • 分派小对象的开支分享小,不要小气往创立。
  • GC最喜好这类小而夭折的对象。
  • 让对象的性命周期尽量短,比方在办法体内创立,使其能尽快地在YoungGC中被接纳,不会提升(romote)到大哥代(OldGeneration)。
2、对象分派的优化

基于年夜部分对象都是小而夭折,而且不存在多线程的数据合作。这些小对象的分派,会优先在线程公有的TLAB平分配,TLAB中创立的对象,不存在锁乃至是CAS的开支。
TLAB占用的空间在EdenGeneration。
当对象对照年夜,TLAB的空间不敷以放下,而JVM又以为以后线程占用的TLAB残剩空间还充足时,就会间接在EdenGeneration上分派,此时是存在并发合作的,以是会有CAS的开支,但也还好。
当对象年夜到EdenGeneration放不下时,JVM只能实验往OldGeneration分派,这类情形必要尽量制止,由于一旦在OldGeneration分派,这个对象就只能被OldGeneration的GC或是FullGC接纳了。
3、不成变对象的优点

GC算法在扫描存活对象时一般必要从ROOT节点入手下手,扫描一切存活对象的援用,构建出对象图。
不成变对象对GC的优化,次要表现在OldGeneration中。
能够设想一下,假如存在OldGeneration的对象援用了YoungGeneration的对象,那末在每次YoungGC的过程当中,就必需思索到这类情形。
HotspotJVM为了进步YoungGC的功能,制止每次YoungGC都扫描OldGeneration中的对象援用,接纳了卡表(CardTable)的体例。
复杂来讲,当OldGeneration中的对象产生对YoungGeneration中的对象发生新的援用干系或开释援用时,城市在卡表中呼应的标志上标志为脏(dirty),而YoungGC时,只必要扫描这些dirty的项就能够了。
可变对象对别的对象的援用干系大概会频仍变更,而且有大概在运转过程当中持有愈来愈多的援用,出格是容器。这些城市招致对应的卡表项被频仍标志为dirty。
而不成变对象的援用干系十分不乱,在扫描卡表时就不会扫到它们对应的项了。
注重,这里的不成变对象,不是指仅仅本身援用不成变的final对象,而是真实的ImmutableObjects
4、援用置为null的传说

初期的良多Java材料中城市提到在办法体中将一个变量置为null可以优化GC的功能,相似上面的代码:
1
2
3
List<String>list=newArrayList<String>();
//somecode
list=null;//helpGC

现实上这类做法对GC的匡助微不足道,偶然候反而会招致代码凌乱。
我记得几年前@rednaxelafx在HLLVM小组中具体叙述过这个成绩,原帖我没找到,结论基础就是:


  • 在一个十分年夜的办法体内,对一个较年夜的对象,将其援用置为null,某种水平上能够匡助GC。
  • 年夜部分情形下,这类举动都没有任何优点。
以是,仍是早点保持这类“优化”体例吧。
GC比我们设想的更伶俐。
5、手动档的GC

在良多Java材料上都有上面两个奇技淫巧:


  • 经由过程Thread.yield()让出CPU资本给别的线程。
  • 经由过程System.gc()触发GC。
现实上JVM从不包管这两件事,而System.gc()在JVM启动参数中假如同意显式GC,则会触发FullGC,关于呼应敏感的使用来讲,几近同等于他杀。
So,让我们切记两点:


  • NeveruseThread.yield()。
  • NeveruseSystem.gc()。除非你真的必要接纳NativeMemory。
第二点有个NativeMemory的破例,假如你在以了局景:


  • 利用了NIO大概NIO框架(Mina/Netty)
  • 利用了DirectByteBuffer分派字节缓冲区
  • 利用了MappedByteBuffer做内存映照
因为NativeMemory只能经由过程FullGC(或是CMSGC)接纳,以是除非你十分分明这时候真的有需要,不然不要容易挪用System.gc(),且行且爱惜。
别的为了避免某些框架中的System.gc挪用(比方NIO框架、JavaRMI),倡议在启动参数中加上-XX:+DisableExplicitGC来禁用显式GC。
这个参数有个伟大的坑,假如你禁用了System.gc(),那末下面的3种场景下的内存就没法接纳,大概形成OOM,假如你利用了CMSGC,那末能够用这个参数替换:-XX:+ExplicitGCInvokesConcurrent。
关于System.gc(),能够参考@bluedavy的几篇文章:


  • CMSGC会不会接纳DirectByteBuffer的内存
  • 说说在Java启动参数上我犯的错
  • java.lang.OutOfMemoryError:Mapfailed
6、指定容器初始化巨细

Java容器的一个特性就是能够静态扩大,以是一般我们都不会往思索初始巨细的设置,不敷了归正会主动扩容呗。
可是扩容不料味着没有价值,乃至是很高的价值。
比方一些基于数组的数据布局,比方StringBuilder、StringBuffer、ArrayList、HashMap等等,在扩容的时分都必要做ArrayCopy,关于不休增加的布局来讲,经由多少次扩容,会存在大批无用的老数组,而接纳这些数组的压力,全城市加在GC身上。
这些容器的机关函数中一般都有一个能够指定巨细的参数,假如关于某些巨细能够预估的容器,倡议加上这个参数。
但是由于容器的扩容并非比及容器满了才扩容,而是有必定的比例,比方HashMap的扩容阈值和负载因子(loadFactor)相干。
GoogleGuava框架关于容器的初始容量供应了十分便利的工具办法,比方:
1
2
3
4
5
6
7
Lists.newArrayListWithCapacity(initialArraySize);
Lists.newArrayListWithExpectedSize(estimatedSize);
Sets.newHashSetWithExpectedSize(expectedSize);
Maps.newHashMapWithExpectedSize(expectedSize);

如许我们只需传进预估的巨细便可,容量的盘算就交给Guava来做吧。
反例:假如接纳默许无参机关函数,创立一个ArrayList,不休增添元素直到OOM,那末在此过程当中会招致:


  • 屡次数组扩容,从头分派更年夜空间的数组
  • 屡次数组拷贝
  • 内存碎片
7、对象池

为了削减对象分派开支,进步功能,大概有人会接纳对象池的体例来缓存对象汇合,作为复用的手腕。
可是对象池中的对象因为在运转期临时存活,年夜部分会提升到OldGeneration,因而没法经由过程YoungGC接纳。
而且一般……没有甚么效果。
关于对象自己:


  • 假如对象很小,那末分派的开支原本就小,对象池只会增添代码庞大度。
  • 假如对象对照年夜,那末提升到OldGeneration后,对GC的压力就更年夜了。
从线程平安的角度思索,一般池都是会被并发会见的,那末你就必要处置好同步的成绩,这又是一个年夜坑,而且同步带来的开支,一定比你从头创立一个对象小
关于对象池,独一符合的场景就是当池中的每一个对象的创立开支很年夜时,缓存复用才成心义,比方每次new城市创立一个毗连,或是依附一次RPC。
好比说:


  • 线程池
  • 数据库毗连池
  • TCP毗连池
即便你真的必要完成一个对象池,也请利用成熟的开源框架,比方ApacheCommonsPool。
别的,利用JDK的ThreadPoolExecutor作为线程池,不要反复造轮子,除非当你看过AQS的源码后以为你能够写得比DougLea更好。
8、对象感化域

尽量减少对象的感化域,即性命周期。

java比较简单,没有C++的烦琐,但学习时最好有C++为基础.与JSP和SQL起应用,功能强大.
简单生活 该用户已被删除
沙发
发表于 2015-1-20 19:21:14 | 只看该作者
J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。
若相依 该用户已被删除
板凳
发表于 2015-1-23 13:01:19 | 只看该作者
是一种使用者不需花费很多时间学习的语言
爱飞 该用户已被删除
地板
发表于 2015-1-31 15:57:23 | 只看该作者
其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。
变相怪杰 该用户已被删除
5#
发表于 2015-2-6 20:28:24 | 只看该作者
Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本—J道。Jive(J道版)是由中国Java界大名 鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站
6#
发表于 2015-2-9 22:41:18 | 只看该作者
不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
小魔女 该用户已被删除
7#
发表于 2015-2-19 15:53:04 | 只看该作者
你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。
灵魂腐蚀 该用户已被删除
8#
发表于 2015-3-6 15:06:22 | 只看该作者
Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台
金色的骷髅 该用户已被删除
9#
发表于 2015-3-7 18:05:12 | 只看该作者
接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。
透明 该用户已被删除
10#
发表于 2015-3-9 05:25:13 | 只看该作者
至于JDBC,就不用我多说了,你如果用java编过存取数据库的程序,就应该很熟悉。还有,如果你要用Java编发送电子邮件的程序,你就得看看Javamail 了。
只想知道 该用户已被删除
11#
发表于 2015-3-11 01:29:50 | 只看该作者
自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
分手快乐 该用户已被删除
12#
 楼主| 发表于 2015-3-17 18:07:16 | 只看该作者
让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-24 01:06

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表