问题、探究过程和解决方法:
在接手一个新的项目构建的过程中,遇到了构建项目过程中,项目一直处于parsing java的过程
打开构建日志的位置
日志位置:
查询构建日志(build-log)发现 项目触发了很多的低内存信号,然后可以猜测afterGc 是触发了回收机制。
解决方法:
1.修改idea64.exe.vmoptions 中的-Xms 和-Xmx 的值,但修改后还是出现同样的错误,无效
2.重装idea,无效
3.重新刷新缓存,方法File-> Invalidate Caches / Restart... ,清除缓存并且重启,重启后idea会重新给这个项目建立索引,无效
4.根据同事的帮助,修改File -> settings -> Build,Execution,Deployment->Compiler->Build process heap size ,改大一些后再次编译,成功
反思:
这里的配置选项说的很清楚了,是构建过程堆内存,那么一般来说 我们只知道(起码我是这样的),堆内存是运行时期用来存放对象的地方,具体的内存可以回忆一下:
那么编译时期,为什么要使用堆内存呢?
这个问题其实很明显,编译的过程会解析语法树、检查死锁、分析逃逸之类的一系列的工作,使用一部分内存是很明显需要的。
为什么设置的编译过程堆内存不自动扩展呢?
首先明确的是 内存的申请和释放都是操作系统的内核态系统调用,频繁的申请和释放会降低性能。
如果可以自动扩展,那么为了保护执行时期需要使用的大量内存,就必然会被释放,这就导致前面说的降低性能。
那么更好的方法是什么呢?
复用!这也是运行时期GC的目的,实际上我们也证明了构建过程会GC复用内存,从上面我们的构建日志中发现的GC过程可以知道。
总结:
我认为这里的堆内存会在编译期间使用,然后结束编译期,即转为class文件后,释放这些内存。从进程的角度看,编译时期,是一个javac程序来执行编译,而完成后由java程序来执行运行。
我们来实验一下。
实验开始前:
开始编译后:
这里JAVA程序,内存是慢慢增加上来的,一开始只有100m左右,CPU满载的原因找到了,javac的内存不够大,导致一直GC回收,猜测需要所有java文件都读到内存后才开始写入class文件。
编译结束后:
运行开始后:这个不演示图片了,这个必然不可能没有一个JAVA Platform SE 程序在跑,没有我直播倒立洗头,截图为证
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
待解决的问题:
那么为什么是堆内存呢?
这个我也不知道,衍生的问题还有 既然堆内存在编译时期就已经存在,那么会不会编译时期已经存在所有的运行时期内存分布呢?
运行时期内存分布相信大家都很熟悉了 ,如下图所示:
堆和方法区是所有线程共享的,而绿色的三个区域是线程私有的。