专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » java占用内存:学习如何使 Java 应用程序启动更快以及占用更少的内存 »正文

java占用内存:学习如何使 Java 应用程序启动更快以及占用更少的内存

来源: 发布时间:星期三, 2009年4月1日 浏览:12次 评论:0
如今 Java 应用面临个问题:它们惟可用容器是 Java 虚拟机(Java virtual machineJVM)进程自身需要多个 JVM 来彼此隔离 Java 应用这会带来两个主要负面影响个是每次 JVM 所花费启动时间第 2个是每个 JVM 所需内存占用考虑到这些开销以及不能在个 JVM 中隔离应用很显然需要进行些基础性工作才能解决这些问题答案就是共享类在本文中IBM Java Technology Center Development Team 成员 Lakshmi Shankar、Simon Burns 和 Roshan Nichani 讨论了 JVM 中共享类背后概念、它们工作原理以及用户如何利用这种技术他们还讨论了这种技术几种当前实现以及在将来会有什么样应用JAVA中文站社区门户~8J-Hey yLv;B
要真正彼此隔离 Java 应用实质上需要多个 JVM然而启动成本和内存占用使这种方式不那么理想而共享类可以同时解决这两个问题在多 JVM 环境中共享类通过将组核心系统类装载到共享内存中可以在多个 JVM 中共享这些类这些共享类放到内存个共享区域中它们在这里对所有 JVM 都是保持结果共享类只需要在第次使用时装载到内存中这消除了在以后每次 JVM 时装载它们固定成本并减少了每个 JVM 中内存占用
:k5fM$L&I d*X"G%c
1D^!u\jIBM 在 z/OS 平台上实现了共享类技术Apple Computer Inc. 在 Mac OS X 上实现了名为 Java Shared Archive(JSA)种共享类而 Sun 在 J2SE 1.5 版中引入了基于 JSA 技术 Class Data Sharing (CDS)让我们分析下这些实现是如何工作
[M Ty'ndC(bJAVA中文站社区门户^IY,?+VjA
IBM 实现JAVA中文站社区门户3g C(W P];{
自 J2SE 1.3.1 以来IBM 就在 z/OS 平台上提供了共享类技术实现这种实现是通过让个主(或称 master) JVM 将核心系统类装载到共享内存完成那么这到底是什么意思呢?
%| lkKd+p4IgSJAVA中文站社区门户,Qib]l
分解堆
2Mz;V.vz*Y d ?内存分为共享堆和 Java 堆主 JVM 将系统堆(即共享堆)分配到共享内存中这里是放置系统类地方系统堆在主 JVM 生存周期中直存在并且不会受到垃圾收集(GC)影响个后续(或者worker)JVM 附加到这个系统堆上如图 1 所示并为自己 Java 堆分配非共享内存它会受垃圾收集影响Java 堆包含特定于每个 worker JVM 运行应用非共享类和所有例子化对象
3I}+o+VE,t Dx5p
7Q [1f0BDTG{L$O图 1. 共享类分解堆JAVA中文站社区门户;z'EYT!J5S(ei

y%qC,~ o*uK$R(A
:n5Wbp,MTT共享类装载器JAVA中文站社区门户!C{6H0~ y9y#h7K"SRS
每个 worker JVM 都可以通过将类放到共享类装载器 path 中而将它们装载到共享堆中共享类和普通类装载方式样??使用 parent-delegation 模式
[6yA4^A&OJAVA中文站社区门户.r l`kEtu#U1Y
层次结构中个类装载器检查其缓存Cache确定这个类是否已经装载如果还没有装载那么类装载器就向其父类装载器传递个检查装载请求这样直上溯到层次结构顶部 primordial 或者 bootstrap 类装载器如果没有在任何缓冲区中发现这个类那么每个类装载器都会试图从自己存储库中装载这个类如果成功就返回这个类否则它将请求传递给层次结构中下面装载器这种模型保证了首先检查最受信任存储库并防止信任程度低代码通过采用和核心 API 成员相同名字代替受信任核心 API 类JAVA中文站社区门户W In*\Z.~
JAVA中文站社区门户sst]"k,Wdco
如果类是 primordial 类或者定义类装载器是共享类装载器那么类对象将在共享堆中创建并且类标记为共享类图 2 显示了 bootstrap 类装载器位于类装载器层次结构顶部并负责装载核心 API 中这些类是信任程度最高扩展类装载器装载 extensions 目录中标准扩展 JAR 文件中共享应用类装载器可以用于共享用户或者应用JAVA中文站社区门户6bZAqH

wL"isfgJ$S h图 2. 类装载器层次结构
o{nP@*[4hJAVA中文站社区门户I,\4?RE0Q.y

N4f Y8toKSzSV`但是在这种实现中类到底是如何由多个 JVM 共享呢?
%n z3h!@[.gj2c
}Qc(Nt"d假定 JVM 1 装载了 java/lang/String这是个由 bootstrap 类装载器装载系统类如果 JVM 2 想要装载 java/lang/String由于它不能访问 JVM 1 bootstrap 类装载器缓存Cache所以它必须使用自己 bootstrap 类装载器重新装载这个类在这个例子中JVM 不共享任何类如图 3 所示JAVA中文站社区门户;v f~G.r.C.cY2[X
JAVA中文站社区门户EEzJ1CS
图 3. 类没有跨 JVM 共享
3^-I,g UVxJAVA中文站社区门户y OH7G(b

}qps*QW6?/q3ewW因此最好让 JVM 共享相同如图 4 所描绘
YK/Zl1{ a_#v1qJAVA中文站社区门户e:AuI*|4E&L/M
图 4. 跨 JVM 共享JAVA中文站社区门户6N#{`f8W$cC

&I+_4`2Q(w:@(["Z
}*z(p'zm-d S要解决这个问题通过创建个名为 全局类缓存Cache将类缓存Cache概念加以扩展每个 JVM 类装载器必须在这个 上注册当共享类装载器装载个类时它被同时放到本地类缓存Cache和 中(如图 5 所示)这样做使得其他 JVM 中类装载器(在 上注册)不用装载它就可以访问这个类JAVA中文站社区门户)E3d)T \O%O ^$U F8O

a8hdiNq:q图 5. Namespace 跨 JVM 共享JAVA中文站社区门户/SJ7I3e4Pi
JAVA中文站社区门户8}1f0`6`5yJ.g2^
JAVA中文站社区门户x O"Ep6l
保护域
-S3k5lwMqC4l类装载器有个或者多个代码源对象(从其中装载类 JAR 文件或者目录)这些对象用于创建保护域它被传递给 Class 思路方法使用共享类其他 JVM 将需要这个信息但是不能共享保护域它们包含本地信息为了解决这个问题将代码源放到系统堆中打包信息也需要共享
fIAo&`JAVA中文站社区门户V^i5mP
竞争条件
(e)mc^'f4qEC6@O由于 JVM 会读取和写入共享数据需要有种思路方法处理竞争条件最简单方式是使用全局块不过出于性能和伸缩性原因应当谨慎地使用它们
#SuN"xtM$Hn ~JAVA中文站社区门户,x X3| J0F5uW| BD{
种避免锁住所有 JVM 思路方法是使用开放式原子更新(optimistic atomic updates)例如在装载个类时类装载器将检查其 (在检查其自己本地类缓存Cache后)如果不能找到这个类那么它就会装载它装载后它会自动检查其他 JVM 没有装载这个类然后更新 JAVA中文站社区门户v7~ z%Vn!t2X/i

_?0f;W z W(b全局和本地数据JAVA中文站社区门户*Rz8z*e%rj&t;l1B9x[Q
类中有些信息(如名字)在所有 JVM 中都是而另些信息要求是本地如装载这个类类装载器 每个 JVM 都需要有装载这个类时需要它生成部分本地副本如图 6 所示JVM 中类阴影区域是本地副本系统中类非阴影区域是全局部分JAVA中文站社区门户"h(l2g P9R)qS#u]
JAVA中文站社区门户 |._/S4No8QL9}iY
图 6.共享全局数据和共享本地数据
l.e?I+hSbm
3Zy#q4F+xYCJAVA中文站社区门户\O:KGV
共享类时偶尔会出现个问题是个 JVM 更新个类时(比如通过修改静态字段)所有其他 JVM 都会看到这种改变这种操作是不希望它会造成不可预料结果为了保证隔离性每个 JVM 都有每个共享类所有静态字段副本JAVA中文站社区门户 v"BuDkNU:bbX
JAVA中文站社区门户 ~ L#p0jT
JIT 编译代码JAVA中文站社区门户V'^-a d8gecHw7v
当属于共享类代码由即时(just-in-timeJIT) 编译器编译时它是自动共享这意味着不管由哪个 JVM 编译代码所有 JVM 都会获得性能上好处(而只有个承担 JITing 开销)JAVA中文站社区门户?1dN(Sm@

b%Y;o"JG启动器JAVA中文站社区门户uW i9N7H7l
IBM 实现需要个启动器(launcher)以便控制 JVM 创建这个启动器必须由用户以本机代码编写如清单 1 显示了个举例启动器伪代码:JAVA中文站社区门户~"vQ6jx
JAVA中文站社区门户&B(xT W ?
清单 1. 启动器伪代码
%\Ej;g;eJAVA中文站社区门户*a| mL*T ?KLt}4i l
{ JAVA中文站社区门户 LN V S8X%kT
create Master JVM (and store ed token*);
@1JE$wo2JE q
R2`XXRnHwhile(work to do) { JAVA中文站社区门户y5l T` SX+y
JAVA中文站社区门户w(Hen2_7{fu
create a Worker JVM passing in token from Master JVM;
m0R?*NEJAVA中文站社区门户Z$H+L _Z
do work _disibledevent=>JAVA中文站社区门户2C vl6ii'YE!T
JAVA中文站社区门户fu@7~&X0mP'L
terminate Worker JVM;
6S0Bz.oY [
2DOC9~ ~"C1qP;K}
YkUX4e.r,@B?
/Z{8} @Wq Dterminate Master JVM; JAVA中文站社区门户n,^|!ptL{:D5PMa5HB

JC4[ k~2a7j} JAVA中文站社区门户^V }N0AnE

j7@`cF(hCJAVA中文站社区门户/UK3wCYtM6|
* token ed from the Master JVM is the address of the shared heap.JAVA中文站社区门户ixV%A%kKH

:}\vh[;t`
r*IP)T(VeKJAVA中文站社区门户l~KW7c6^Fa
Apple 实现
6D,q7I\O;cApple 共享类技术实现是 Mac OS X 中 Java 共享档案(Java shared archiveJSA)JAVA中文站社区门户WGfQ)P [s"F

@|it/Nq d实质上JSA 是个内存映射到共享内存文件可以让多个进程(即多个 JVM )访问它安装了 Java Runtime Environment (JRE) 后用系统 JAR 文件中类创建 JSA这些核心类内部表示存储在文档中这个数据是静态因此永远也不会改变这意味着可以共享这些类而不会有任何隔离问题它还意味着这些类永远不会被垃圾收集 Apple JVM 使用般性 GC因此必须保护这些类不被收集这种保护是通过引入 immortal 对象概念来实现JSA 中所有类都指定为 immortalJAVA中文站社区门户DgruzN.T
JAVA中文站社区门户{$se%s{ D
这种技术在默认情况下是可用使用它不需要编写任何特殊??如 IBM 实现所需要启动器这种实现个好处是系统重启后也可以享受它好处不局限于特定 JVM 生存周期不过缺点是局限于组核心类没有提供共享应用类或者 JIT 代码能力
f{ s.J'bH
\ D3~0UASun 实现JAVA中文站社区门户:^$^!^Ic0i
Sun 共享类技术实现称为类数据共享(Class Data SharingCDS)是 J2SE 1.5 中新功能CDS 基于 Apple JSA 实现
p)GDO HJAVA中文站社区门户G6]"F-e$C'XOk
和 JSA 类似 CDS 使用个只读内存映射文档文件这个文件包含核心系统类内部表示并在启动时映射到每个 JVM Java 堆中CDS 文件既可以由 Sun JRE 安装器创建也可以像 Sun CDS 文档中所描述那样手工创建
ykXOF8] r)V&?JAVA中文站社区门户 I/bt:a"J Y'j
同样主要好处是启动时成本节省和降低内存占用启动时间的所以减少是核心类不是用传统类装载机制(即 JVM 次映射所有核心类而不是单独装载每个类)装载所使用内存的所以减少是 JVM 共享了只读类数据而不用每个 JVM 占有自己副本同时类不是用传统机制装载所以 JVM 不会由处理任何未使用思路方法
?^4d5Z7Z$iE
.m.xI+\]^V$Qh.o在撰写本文时候Sun 实现只限于共享核心系统类并且不允许共享应用类或者 JIT 代码应用相对于它所使用核心类越小启动时节省越多
!h:w.U9~5{!plH
0},VPl$U:nfO w根据 Sun CDS 文档在将来共享类功能将扩展到应用以改进大型应用启动成本
QO O E)hJ,CJAVA中文站社区门户-W.H3BZ0CG QA:O
共享类当前应用JAVA中文站社区门户E O @$k!a p'DF
Java 平台用户已经利用了共享类技术本节描述当前部署些应用领域
z}-S R9argJAVA中文站社区门户 QGEY(Rb
事务环境
8O&aX%J H.v#A共享类(不管是系统类还是应用类)对事务环境(如 CICS 和 DB2)中 JVM 启动和内存占用可以有显著效果在这里每个事务或者应用都包装在单独 JVM 中
4O:f Nl:Pt9E1~OZ$`JAVA中文站社区门户x:nH8uaO6h
z/OS 2.3 上 Customer Information Control Transaction Server (CICS TS) 是运行 Java 事务和应用主要商业产品的(目前使用了 IBM JVM 共享类技术)CICS TS 2.3 引入了共享类缓存Cache工具它将共享类功能扩展为它所控制 JVM 池(称为它 JVM)JAVA中文站社区门户IR [X-@E#z

q!E(a;TO%_(kCICS 使用自定义启动器来控制 master JVM 以及所有 worker JVM 启动它们需要服务请求来运行 Java 组件除了系统堆中共享类它们还可以共享 worker JVM 中特殊“中间件类”和些“应用类”如图 7 所示这个共享类缓存Cache工具为 CICS 客户提供了很多好处例如Java 类是由 master JVM 装载每个 CICS 区域(当 CICS 启动时) 装载次而不是每个 JVM 从而在 JVM 中减少所有 worker 类装载成本通过在缓冲区中保留每个类个副本而不是每个 worker JVM 堆个副本共享类缓存Cache工具还减少了 JVM 总体存储需求
(bIP*f'vg1|2k{
4j l G1nKU0h图 7. CICS 中共享类 JAVA中文站社区门户2G)Wb:@q

5GW4HH-cd4GDJAVA中文站社区门户~U1@&xc,f$a-C
在处理大量事务时由更快启动和更有效内存处理而获得好处会显著增加图 8 中第个图显示了共享和非共享 CICS 环境中个简单事务启动时间第 2个图显示整体 JVM 存储成本也分为共享和非共享 CICS 环境可以明显地看出当 JVM 数量增加时每个 JVM 所需要内存减少了(和非共享比较)JAVA中文站社区门户 tCT?Q2q
JAVA中文站社区门户:]7c#x+f n7}c s0N
图 8. 使用共享类 CICS 性能图JAVA中文站社区门户%Yb,g[q%[

t |w7ybT~?8b(Y-OJAVA中文站社区门户'U"^+}x A-_:['vk8v
桌面系统JAVA中文站社区门户9CT#P/U0Q:pns
在 Apple Mac OS X 平台上运行 Java 应用可以自动从这种技术中获得好处Sun J2SE 1.5 用户也会从中受益JAVA中文站社区门户)_!Cc7[U,]0pB

0ae/qq7k共享类将来可能应用
7wm6GTVmY共享类技术有可能为基于 Java 平台其他技术用户带来极大好处本节重点介绍些可能应用JAVA中文站社区门户~ y"^3BG
JAVA中文站社区门户o:Wr%cw(ERj
普及环境
,U,Ws(X@6WjXo谈到运行 Java 应用更小内存占用对普及计算环境(如 PDA 和移动电话)会有显著影响这种环境是由特殊 VM、JIT 编译器和 J2ME 中类构成不过当普及设备变得越来越普遍时需要多 JVM 可能性会增加使用包含核心系统类内存映射文件会显著节省内存这对于普及设备是很关键
aN7Q&v*\#M$_UJAVA中文站社区门户;D_N!Uu,m o)V"A
网格计算JAVA中文站社区门户Q0J r9G)b"L G
在网格计算环境中像 CPU 时间和内存容量这样资源决定了所发生成本优化通常是有好处
S Y_ s x
}(TLs Q`(ea使用共享类可以为网格提供者提供更好运行 Java 能力因此它们可以同时为用户运行更多任务它还使客户每次使用成本更低这使它们具有更高价值为供应商提供更大竞争优势JAVA中文站社区门户s p0iEbp^
JAVA中文站社区门户k9kC6p0jV
Java 应用JAVA中文站社区门户N/k/J.?N?7T
对于复杂 J2EE 应用如 IBM WebSphere可能会装载数千个类如果核心系统类和 WebSphere 类是共享(而不是由每个 JVM 在使用前装载)那么应用启动时间可以有显著缩短这种好处加上内存占用减少可以使 WebSphere 上运行各个应用受益JAVA中文站社区门户a(}k UC4W5Lh

b l"i d*Ag0^对于 Java 用户让应用更快地启动同时保持更低内存占用肯定是有好处如果在启动 Java 应用(如 Eclipse)时核心类已经装载那么这些应用可以共享核心类因而不用在启动时单独装载它们这种方式对于使用 Swing 或者 AWT 应用特别有用这些应用已经由于启动缓慢和占用大量内存而受到报抱怨了
u0?xGYsJAVA中文站社区门户8L*Z$BsR
结束语JAVA中文站社区门户9a Z l.?Q0x GS
本文提供了对 Java 共享类技术概述和般性介绍我们展示了区别共享类和它们所提供好处如 Java 应用启动时间更快和内存占用更小我们还分析了可以利用共享类当前和未来些技术JAVA中文站社区门户$E#gO6f5Up/d7s8X0lJ {
JAVA中文站社区门户7N]&{[)V
所有需要关注启动时间和内存占用 Java 应用都可以通过共享类技术获益当前实现有局限性如有限能力或者不能共享应用类(或者这两者)如果能够解决这些问题那么更多用户会从这种技术中受益使 Java 应用更有吸引力

TAG: Java JAVA java 内存 学习 应用
1

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: