- 浏览: 331329 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (212)
- spring (21)
- design pattern(java) (12)
- linux-shell (28)
- java-thread (20)
- java-collection (6)
- java-reflect (9)
- mysql (11)
- java-io (7)
- java-util&lang&io (3)
- algorithm (3)
- interview (2)
- tools-eclipse (2)
- tools-maven (1)
- web-script (1)
- java组建 (13)
- 博客收藏 (1)
- 架构设计与实践 (10)
- active-mq (6)
- java-jvm&性能&原理 (27)
- tomcat (2)
- flume (1)
- serialization (2)
- git (1)
- cache&redis (8)
- guava (1)
- zookeeper (3)
- socket&tcp&udp&http (6)
- test (1)
最新评论
-
bbls:
有用有用有用
java-jvm-jstack-(监视器和锁的概念) -
王新春:
小侠有点帅哦 写道此流怎么关闭新春这个实现 可以不关闭的,哈哈 ...
源码剖析之java.io.ByteArrayOutputStream -
小侠有点帅哦:
此流怎么关闭新春
源码剖析之java.io.ByteArrayOutputStream -
cumt168:
写的很好为什么初始化参数,年轻代-Xmn10M def new ...
jvm之内存申请过程分析 -
ronin47:
应该是跟共享域名思路差不多,根据cookie的key作判断
跨域:一种通过服务端解决跨域的实现
----------~开篇分享一句话:【纸上得来终觉浅,绝知此事要躬行】~---------------------------------------
前置了解知识:http://wangxinchun.iteye.com/blog/2189321
内存申请过程
1、JVM会试图为相关Java对象在Eden中初始化一块内存区域;
2、当Eden空间足够时,内存申请结束。否则到下一步;
3、JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
4、Survivor区被用来作为Eden及old的中间交换区域,如果Survivor不足以放置eden区的对象,如果old区有空闲,那么直接放置在old区,Survivor区的对象会被移到Old区
5、当old区空间不够时,JVM会在old区进行major collection;
完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误";
1、jvm优先分配在eden区
2、当Eden空间足够时,内存申请结束。
证明:
jvm参数设置:
其中:
-Xmx20M : 堆最大内存是20M
-Xms20M: 初始化也是20M
-Xmn10M :新生代10M,老年代10M
-verbose:gc 输出退出后的日志
-XX:SurvivorRatio=8:eden 为8M s0 s1 各1M
-XX:+PrintGCDetails:打印gc日志的详情
代码:
日志输出:
通过分析main方法中申请2m的内存,内存分配到了eden区。from to tenered区都是没有被使用。
3、JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
证明:
jvm参数设置同上
代码:
日志:
分析:
程序执行逻辑 先申请了1M的内存,然后再次申请8M的内存,考虑内存本身结构会占用内存空间为了避免边界都以9/10的比例来申请。
结果:
先分配了解决1M的内存在eden区,因为再次申请接近8M的内存时,eden区不够,发生了一次young gc,1M的内存分配到了from区,接近8M的内存放在了eden区。
[GC [DefNew: 1250K->1024K(9216K), 0.0015682 secs] 1250K->1062K(19456K), 0.0016006 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
其中
9216K 为eden+from = 8M+1M=9M
19456K 为Xmx-to = 20M-1M = 19M
1250K->1024K :本次young gc 年轻代内存的变化
1250K->1062K :本次young gc 总堆内存的变化
4、Survivor区被用来作为Eden及old的中间交换区域,如果Survivor不足以放置eden区的对象,如果old区有空闲,那么直接放置在old区,Survivor区的对象会被移到Old区
证明:
jvm参数设置同上
程序如下:
日志输出:
分析:首先程序申请了5M的内存,放在了eden区,然后再次申请5M的内存,eden区不够,发生young gc,5M放置在from区,依然不够,故直接放置old 区
结果:eden区 8192*65/100/1024=5M
old区:10240*50/100/1024=5M
5、如果eden区不够,from区也承载不了,恰old区也已承载不了,那么会full gc
证明:
jvm参数配置同上
java代码:
日志输出:
分析:
1、先申请了4M内存,放在eden区。
2、然后申请5M内存时,发生了young gc,无奈4M被安置在了old区,5M放在了eden区
3、再次向eden区申请8M的时候,eden区不够,同时8M还是放不下eden区,于是要full gc,full gc前先进行了young gc,5M 因为没有引用被清理,8M放在old区时,old区满,故full gc 4M也被清除old区。
结果:10240K, 81% used 为8M放在了old区
如果old区不够,会发生错误 java.lang.OutOfMemoryError: Java heap space
日志:
分析:
4M 先是放在eden区,5M申请时gc 4M转入old区,5M留在了eden区,8M申请时,发生gc5M在eden区被清理,因为eden区不够8M,所以分配到old区,old区发生full gc,full gc依然腾不出空间,报错。
注意:5M是在eden区gc时被清理,理由:[GC [DefNew: 5260K->140K(9216K), 0.0008379 secs][Tenured: 4096K->4236K(10240K), 0.0092434 secs] 9356K->4236K(19456K), [Perm : 366K->366K(12288K)], 0.0101605 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 日志显示(Tenured: 4096K->4236K(10240K))无变化,但是eden区和堆总内存变化(DefNew: 5260K->140K(9216K), 9356K->4236K(19456K));
前置了解知识:http://wangxinchun.iteye.com/blog/2189321
内存申请过程
1、JVM会试图为相关Java对象在Eden中初始化一块内存区域;
2、当Eden空间足够时,内存申请结束。否则到下一步;
3、JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
4、Survivor区被用来作为Eden及old的中间交换区域,如果Survivor不足以放置eden区的对象,如果old区有空闲,那么直接放置在old区,Survivor区的对象会被移到Old区
5、当old区空间不够时,JVM会在old区进行major collection;
完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误";
1、jvm优先分配在eden区
2、当Eden空间足够时,内存申请结束。
证明:
jvm参数设置:
-Xmx20M -Xms20M -Xmn10M -verbose:gc -XX:SurvivorRatio=8 -XX:+PrintGCDetails
其中:
-Xmx20M : 堆最大内存是20M
-Xms20M: 初始化也是20M
-Xmn10M :新生代10M,老年代10M
-verbose:gc 输出退出后的日志
-XX:SurvivorRatio=8:eden 为8M s0 s1 各1M
-XX:+PrintGCDetails:打印gc日志的详情
代码:
public class TestEden { public static void main(String[] args) { byte[] b1 = new byte[1024*1024*2]; } }
日志输出:
Heap def new generation total 9216K, used 2704K [0x03ac0000, 0x044c0000, 0x044c0000) eden space 8192K, 33% used [0x03ac0000, 0x03d64230, 0x042c0000) from space 1024K, 0% used [0x042c0000, 0x042c0000, 0x043c0000) to space 1024K, 0% used [0x043c0000, 0x043c0000, 0x044c0000) tenured generation total 10240K, used 0K [0x044c0000, 0x04ec0000, 0x04ec0000) the space 10240K, 0% used [0x044c0000, 0x044c0000, 0x044c0200, 0x04ec0000) compacting perm gen total 12288K, used 2143K [0x04ec0000, 0x05ac0000, 0x08ec0000) the space 12288K, 17% used [0x04ec0000, 0x050d7fe0, 0x050d8000, 0x05ac0000) No shared spaces configured.
通过分析main方法中申请2m的内存,内存分配到了eden区。from to tenered区都是没有被使用。
3、JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
证明:
jvm参数设置同上
代码:
public class TestEden { public static void main(String[] args) { byte[] b1 = new byte[1024*1024*9/10]; byte[] b2 = new byte[1024*1024*8*9/10]; } }
日志:
[GC [DefNew: 1250K->1024K(9216K), 0.0015682 secs] 1250K->1062K(19456K), 0.0016006 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap def new generation total 9216K, used 8560K [0x26ea0000, 0x278a0000, 0x278a0000) eden space 8192K, 92% used [0x26ea0000, 0x275fc308, 0x276a0000) from space 1024K, 100% used [0x277a0000, 0x278a0000, 0x278a0000) to space 1024K, 0% used [0x276a0000, 0x276a0000, 0x277a0000) tenured generation total 10240K, used 38K [0x278a0000, 0x282a0000, 0x282a0000) the space 10240K, 0% used [0x278a0000, 0x278a9920, 0x278a9a00, 0x282a0000) compacting perm gen total 12288K, used 366K [0x282a0000, 0x28ea0000, 0x2c2a0000) the space 12288K, 2% used [0x282a0000, 0x282fba28, 0x282fbc00, 0x28ea0000) ro space 8192K, 67% used [0x2c2a0000, 0x2c802f30, 0x2c803000, 0x2caa0000) rw space 12288K, 53% used [0x2caa0000, 0x2d110180, 0x2d110200, 0x2d6a0000)
分析:
程序执行逻辑 先申请了1M的内存,然后再次申请8M的内存,考虑内存本身结构会占用内存空间为了避免边界都以9/10的比例来申请。
结果:
先分配了解决1M的内存在eden区,因为再次申请接近8M的内存时,eden区不够,发生了一次young gc,1M的内存分配到了from区,接近8M的内存放在了eden区。
[GC [DefNew: 1250K->1024K(9216K), 0.0015682 secs] 1250K->1062K(19456K), 0.0016006 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
其中
9216K 为eden+from = 8M+1M=9M
19456K 为Xmx-to = 20M-1M = 19M
1250K->1024K :本次young gc 年轻代内存的变化
1250K->1062K :本次young gc 总堆内存的变化
4、Survivor区被用来作为Eden及old的中间交换区域,如果Survivor不足以放置eden区的对象,如果old区有空闲,那么直接放置在old区,Survivor区的对象会被移到Old区
证明:
jvm参数设置同上
程序如下:
public class TestEden { public static void main(String[] args) { byte[] b1 = new byte[1024*1024*5]; byte[] b2 = new byte[1024*1024*5]; System.out.println(b1+""+b2); } }
日志输出:
[GC [DefNew: 5448K->140K(9216K), 0.0051311 secs] 5448K->5260K(19456K), 0.0051644 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [B@c17164[B@1fb8ee3 Heap def new generation total 9216K, used 5511K [0x26ea0000, 0x278a0000, 0x278a0000) eden space 8192K, 65% used [0x26ea0000, 0x273deb58, 0x276a0000) from space 1024K, 13% used [0x277a0000, 0x277c32a8, 0x278a0000) to space 1024K, 0% used [0x276a0000, 0x276a0000, 0x277a0000) tenured generation total 10240K, used 5120K [0x278a0000, 0x282a0000, 0x282a0000) the space 10240K, 50% used [0x278a0000, 0x27da0010, 0x27da0200, 0x282a0000) compacting perm gen total 12288K, used 366K [0x282a0000, 0x28ea0000, 0x2c2a0000) the space 12288K, 2% used [0x282a0000, 0x282fbb28, 0x282fbc00, 0x28ea0000) ro space 8192K, 67% used [0x2c2a0000, 0x2c802f30, 0x2c803000, 0x2caa0000) rw space 12288K, 53% used [0x2caa0000, 0x2d110180, 0x2d110200, 0x2d6a0000)
分析:首先程序申请了5M的内存,放在了eden区,然后再次申请5M的内存,eden区不够,发生young gc,5M放置在from区,依然不够,故直接放置old 区
结果:eden区 8192*65/100/1024=5M
old区:10240*50/100/1024=5M
5、如果eden区不够,from区也承载不了,恰old区也已承载不了,那么会full gc
证明:
jvm参数配置同上
java代码:
public class TestEden { public static void main(String[] args) { byte[] b1 = new byte[1024*1024*4]; byte[] b2 = new byte[1024*1024*5]; b1=null; b2=null; byte[] b3 = new byte[1024*1024*8]; } }
日志输出:
[GC [DefNew: 4424K->140K(9216K), 0.0056340 secs] 4424K->4236K(19456K), 0.0056837 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] [GC [DefNew: 5260K->140K(9216K), 0.0008662 secs][Tenured: 4096K->140K(10240K), 0.0084034 secs] 9356K->140K(19456K), [Perm : 366K->366K(12288K)], 0.0093567 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] Heap def new generation total 9216K, used 163K [0x26ea0000, 0x278a0000, 0x278a0000) eden space 8192K, 2% used [0x26ea0000, 0x26ec8fc8, 0x276a0000) from space 1024K, 0% used [0x276a0000, 0x276a0000, 0x277a0000) to space 1024K, 0% used [0x277a0000, 0x277a0000, 0x278a0000) tenured generation total 10240K, used 8332K [0x278a0000, 0x282a0000, 0x282a0000) the space 10240K, 81% used [0x278a0000, 0x280c3228, 0x280c3400, 0x282a0000) compacting perm gen total 12288K, used 366K [0x282a0000, 0x28ea0000, 0x2c2a0000) the space 12288K, 2% used [0x282a0000, 0x282fba68, 0x282fbc00, 0x28ea0000) ro space 8192K, 67% used [0x2c2a0000, 0x2c802f30, 0x2c803000, 0x2caa0000) rw space 12288K, 53% used [0x2caa0000, 0x2d110180, 0x2d110200, 0x2d6a0000)
分析:
1、先申请了4M内存,放在eden区。
2、然后申请5M内存时,发生了young gc,无奈4M被安置在了old区,5M放在了eden区
3、再次向eden区申请8M的时候,eden区不够,同时8M还是放不下eden区,于是要full gc,full gc前先进行了young gc,5M 因为没有引用被清理,8M放在old区时,old区满,故full gc 4M也被清除old区。
结果:10240K, 81% used 为8M放在了old区
如果old区不够,会发生错误 java.lang.OutOfMemoryError: Java heap space
public class TestEden { public static void main(String[] args) { byte[] b1 = new byte[1024*1024*4]; byte[] b2 = new byte[1024*1024*5]; b2=null; byte[] b3 = new byte[1024*1024*8]; } }
日志:
[GC [DefNew: 4424K->140K(9216K), 0.0057531 secs] 4424K->4236K(19456K), 0.0058056 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [GC [DefNew: 5260K->140K(9216K), 0.0008379 secs][Tenured: 4096K->4236K(10240K), 0.0092434 secs] 9356K->4236K(19456K), [Perm : 366K->366K(12288K)], 0.0101605 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] [Full GC [Tenured: 4236K->4233K(10240K), 0.0075081 secs] 4236K->4233K(19456K), [Perm : 366K->365K(12288K)], 0.0075750 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at test.test.TestEden.main(TestEden.java:8) Heap def new generation total 9216K, used 251K [0x26ea0000, 0x278a0000, 0x278a0000) eden space 8192K, 3% used [0x26ea0000, 0x26edefd0, 0x276a0000) from space 1024K, 0% used [0x276a0000, 0x276a0000, 0x277a0000) to space 1024K, 0% used [0x277a0000, 0x277a0000, 0x278a0000) tenured generation total 10240K, used 4233K [0x278a0000, 0x282a0000, 0x282a0000) the space 10240K, 41% used [0x278a0000, 0x27cc2630, 0x27cc2800, 0x282a0000) compacting perm gen total 12288K, used 365K [0x282a0000, 0x28ea0000, 0x2c2a0000) the space 12288K, 2% used [0x282a0000, 0x282fb688, 0x282fb800, 0x28ea0000) ro space 8192K, 67% used [0x2c2a0000, 0x2c802f30, 0x2c803000, 0x2caa0000) rw space 12288K, 53% used [0x2caa0000, 0x2d110180, 0x2d110200, 0x2d6a0000)
分析:
4M 先是放在eden区,5M申请时gc 4M转入old区,5M留在了eden区,8M申请时,发生gc5M在eden区被清理,因为eden区不够8M,所以分配到old区,old区发生full gc,full gc依然腾不出空间,报错。
注意:5M是在eden区gc时被清理,理由:[GC [DefNew: 5260K->140K(9216K), 0.0008379 secs][Tenured: 4096K->4236K(10240K), 0.0092434 secs] 9356K->4236K(19456K), [Perm : 366K->366K(12288K)], 0.0101605 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 日志显示(Tenured: 4096K->4236K(10240K))无变化,但是eden区和堆总内存变化(DefNew: 5260K->140K(9216K), 9356K->4236K(19456K));
评论
1 楼
cumt168
2016-05-11
写的很好
为什么初始化参数,年轻代-Xmn10M
def new generation total 9216K, used 2704K [0x03ac0000, 0x044c0000, 0x044c0000)
而实际上显示只有9M呢?
为什么初始化参数,年轻代-Xmn10M
def new generation total 9216K, used 2704K [0x03ac0000, 0x044c0000, 0x044c0000)
而实际上显示只有9M呢?
发表评论
-
垃圾回收算法详解
2017-05-17 16:42 450可回收对象的判定【收藏,非原创】 讲算法之前,我们先要 ... -
垃圾回收算法&STOP The World
2017-05-15 11:50 620目前所有的新生代gc都是需要STW的: Seria ... -
java-jvm-jhat
2017-05-14 21:04 513功能:可以分析jmap dump下的hprof文件 一般 ... -
java-jvm-jinfo
2017-05-14 20:57 647jinfo: 1、输出 当前java进程启动的相关配置信息 ... -
jvm-gc 日志解读【转载】
2017-05-14 17:34 438转载自:http://ifeve.com/useful-j ... -
大量异常带来性能的影响
2017-05-09 19:08 635感受大量构造异常带来的性能影响: package com; ... -
iotop&iostat (load高 IO高的问题排查)
2017-04-27 20:40 2039目标:使用iotop&top&jstack ... -
java-jvm-jstack-(监视器和锁的概念)
2017-04-06 16:52 6425下面这段jstack的栈信息里,有一个死锁 其中: T ... -
java-jvm-jstack-线程状态
2017-03-31 14:42 2526常见的线程状态: RUNNABLE:正在执行的线程 注 ... -
java-jvm-cpu (cpu)高问题排查
2017-03-28 21:07 32901、通过top命令发现 cpu高的进程 根据top命令, ... -
java-jvm-jstack
2016-08-05 11:07 2157jstack用于打印出给定的java进程ID或core fi ... -
java-jvm好文收集
2016-08-05 10:50 387非常详细GC学习笔记http://blog.csdn.ne ... -
java-jvm-jstat
2016-08-05 10:30 597stat用于监控基于HotSpot ... -
java-jvm-jmap(高内存排查)
2016-07-29 13:51 3756功能:打印出某个java进程(使用pid)内存内的,所有‘对象 ... -
java-jvm-jps
2016-07-29 13:42 421jsp -q 只显示pid,不显示class名称,jar文件 ... -
OutOfMemoryError溢出
2016-03-29 23:29 796Java堆溢出: java.lang.OutOfMemor ... -
垃圾回收器的分类
2016-03-29 22:23 683基础: 串行收集器: DefNew:是使用-XX:+UseSe ... -
ClassLoader-线程上下文类加载器
2015-04-16 10:54 1114线程上下文类加载器 :http://blog.csdn.net ... -
ClassLoader-热替换
2015-04-05 20:27 2676https://www.ibm.com/developer ... -
ClassLoader-学习
2015-04-05 19:03 1020相关文章:https://www.ib ...
相关推荐
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
也有分析认为,谷歌并不想做一个简单的手机终端制造商或者软件平台开发商,而意在一统传统互联网和 移 动互联网。----------------------------------- Android 编程基础 4 Android Android Android Android 手机新...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...
JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...