先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
正文
- 演示内存的分配策略
*/
public class Demo2_1 {
private static final int _512KB = 512 * 1024;
private static final int _1MB = 1024 * 1024;
private static final int _6MB = 6 * 1024 * 1024;
private static final int _7MB = 7 * 1024 * 1024;
private static final int _8MB = 8 * 1024 * 1024;
//加入Java开发交流君样:756584822一起吹水聊天
// -Xms20M -Xmx20M -Xmn10M : 堆初始与最大大小都是20M,新生代的大小为10M.
// -XX:+UseSerialGC : 为了学习方便,采用这个垃圾回收器,默认的垃圾回收器并不是这个。
// -XX:+PrintGCDetails -verbose:gc :打印详细信息
// -XX:-ScavengeBeforeFullGC :在Full GC 前进行 Minor GC.
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
ArrayList<byte[]> list = new ArrayList<>();
list.add(new byte[_8MB]);
list.add(new byte[_8MB]);
}).start();
System.out.println(“sleep…”);
Thread.sleep(1000L);
}
}
情况1执行结果
可以看到即使用户没有创建对象,系统对象也要占据一部分堆内存空间。
Heap
def new generation total 9216K, used 2341K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
// 新生代的空间总的大小为9216K,这里没有把To空间给计算进去,系统任务To的空间是分配是不可用的,所以不是10M,已经使用了2341K,[]内部则是内存地址范围。
eden space 8192K, 28% used [0x00000000fec00000, 0x00000000fee49420, 0x00000000ff400000)
//
from space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
tenured generation total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
// 老年代大小为10M,可以看到没有任何空间使用
//加入Java开发交流君样:756584822一起吹水聊天
the space 10240K, 0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
Metaspace used 3394K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 378K, capacity 388K, committed 512K, reserved 1048576K
Java的内存对象都是分配在堆上吗
情况2:新生代堆空间放满,触发GC
public static void main(String[] args) throws InterruptedException {
ArrayList<byte[]> list = new ArrayList<>();
list.add(new byte[_7MB]); // 系统类占用2341K,加上new的7MB触发垃圾回收
}
情况2执行结果
[GC (Allocation Failure) [DefNew: 2342K->696K(9216K), 0.0029193 secs] 2342K->696K(19456K), 0.0029867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
// GC:minor GC(新生代垃圾回收) FUll GC (老年代垃圾回收)
// [Times: user=0.00 sys=0.00, real=0.00 secs] 垃圾回收执行时间
Heap
def new generation total 9216K, used 8110K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 90% used [0x00000000fec00000, 0x00000000ff33d8c0, 0x00000000ff400000)
from space 1024K, 67% used [0x00000000ff500000, 0x00000000ff5ae100, 0x00000000ff600000)
to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
tenured generation total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
Metaspace used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
//加入Java开发交流君样:756584822一起吹水聊天
class space used 395K, capacity 428K, committed 512K, reserved 1048576K
情况三: 新生代内存随着对象的增多放不下了
public static void main(String[] args) throws InterruptedException {
ArrayList<byte[]> list = new ArrayList<>();
list.add(new byte[_7MB]);
list.add(new byte[_512KB]);
list.add(new byte[_512KB]);
}
执行结果
新生代放不下,将新生代的对象放置到老年代。
[GC (Allocation Failure) [DefNew: 2342K->670K(9216K), 0.0022591 secs] 2342K->670K(19456K), 0.0023131 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 8678K->538K(9216K), 0.0061246 secs] 8678K->8354K(19456K), 0.0061637 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
def new generation total 9216K, used 1132K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 7% used [0x00000000fec00000, 0x00000000fec94930, 0x00000000ff400000)
from space 1024K, 52% used [0x00000000ff400000, 0x00000000ff486a00, 0x00000000ff500000)
to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
tenured generation total 10240K, used 7815K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 76% used [0x00000000ff600000, 0x00000000ffda1f80, 0x00000000ffda2000, 0x0000000100000000)
Metaspace used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
//加入Java开发交流君样:756584822一起吹水聊天
class space used 395K, capacity 428K, committed 512K, reserveed 1048576K
情况四:一开始直接分配大于新生代的内存,如果老年代放的下,则直接放到老年代
public static void main(String[] args) throws InterruptedException {
ArrayList<byte[]> list = new ArrayList<>();
list.add(new byte[_8MB]);
}
执行结果
Heap
//加入Java开发交流君样:756584822一起吹水聊天
def new generation total 9216K, used 2507K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 30% used [0x00000000fec00000, 0x00000000fee72ca8, 0x00000000ff400000)
from space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
tenured generation total 10240K, used 8192K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 80% used [0x00000000ff600000, 0x00000000ffe00010, 0x00000000ffe00200, 0x0000000100000000)
Metaspace used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
class space used 395K, capacity 428K, committed 512K, reserved 1048576K
当内存比较紧张的时候,即新生代内存放不下的时候,有时候会直接将对象分配到老年代,或者直接在回收次数较少(未达到15次)的情况下,直接将新生代对象弄到老年代。【资料获取】
====================================================================
| 名称 | 特点 | 适合场景 | 目标 | 新生代 | 老年代 |
| — | — | — | — | — | — |
| 串行垃圾回收器 | 单线程 | 堆内存小,适合个人电脑(cpu个数) | | 采用复制的垃圾回收算法 | 采用标记+整理的垃圾回收算法 |
| 吞吐量优先垃圾回收器 | 多线程 | 堆内存大,多核CPU | 并行,让单位时间内STW的时间最短 | 复制算法 | 标记+拷贝 |
| 响应时间优先的垃圾回收器(简称CMS) | 多线程 | 堆内存大,多核CPU | 并发,尽可能让单次STW最短 | 复制算法 | 标记清除算法产生内存碎片需要退化成单线程的垃圾整理回收器 |
CMS垃圾回收器后来被G1垃圾回收器取代。
开启串行垃圾回收器的JVM参数
-XX:+UseSerialGC = Serial + SerialOld
// Serial:工作在新生代,采用复制的垃圾回收算法
// SerialOld:工作在老生代,采用标记+整理的垃圾回收算法
[
](https://jq.qq.com/?_wv=1027&k=0IsBuUb0)
总结:触发垃圾回收时,让多个线程在一个安全点停下来,然后使用单线程的垃圾回收器去进行垃圾回收,垃圾回收完成后,再让其他线程运行。
开启吞吐量优先的垃圾回收器的JVM参数
开启/关闭的参数
默认的多线程垃圾回收器,前者是开启新生代回收器,采用复制算法,后者是开启老年代回收器,采用标记+拷贝算法。下面选项只要开启一个,那么另外一个也会开启。
-XX:+UseParallelGC , -XX:+UseParallelOldGC
开启自适应动态调整新生代的大小,晋升阈值
-XX:+UseAdaptiveSizePolicy
二个指标调整的参数(ParallelGC会根据设定的指标去调整堆的大小到达下面期望设定的目标)
指标1)1/(1+ratio) = 垃圾回收的时间/总的运行时间
ratio默认值时99,即垃圾回收的时间不超过总时间1%。但一般设为19
如果达不到目标,ParallelGC会调整堆内存大小来达到这个目标,通常是调大,这样垃圾回收的次数会减少,从而提高吞吐量
-XX:GCTimeRatio=ratio
指标2)每次垃圾回收的时间限制( 最大暂停的毫秒数)
默认值是200ms
显然将堆内存空间变小有助于减少每次垃圾回收的时间
-XX:MaxGCPauseMillis=ms
总结:显然指标1)与指标2)是有冲突的。
-XX:ParallelGCThreads=n //垃圾回收并行的线程数目
[
](https://jq.qq.com/?_wv=1027&k=0IsBuUb0)
总结:采用多线程方式进行垃圾回收,垃圾回收的线程数目通常根据CPU的核数进行设置。在垃圾回收阶段,并行的垃圾回收线程会充分占用CPU。在非垃圾回收阶段,用户线程会充分利用CPU资源。
缺点:采用的标记清除算法产生内存碎片需要退化成单线程的垃圾整理回收器,造成响应时间变长。
开启的JVM参数
注意这个是并发的采用标记清除算法的垃圾回收,这里区别于之前的垃圾回收器,该垃圾回收器能够在进行垃圾回收的同时运行其他非垃圾回收线程(也存在时间阶段需要停止,但不是所有阶段停止)。
老年代并发的垃圾回收器会出现失败的情况,这时老年代垃圾回收器会退化成单线程的垃圾回收器(SerialOld)
-XX:+UseConcMarkSweepGC // use concurrent mark sweep(会产生垃圾碎片) 工作在老年代的垃圾回收器
-XX:+UseParNewGC // 工作在新生代的垃圾回收器
//加入Java开发交流君样:756584822一起吹水聊天
重要的初始参数
-XX:ParallelGCThreads=n // 并行的垃圾回收线程数,通常等于CPU的核心数(垃圾回收并行阶段)
-XX:ConcGCThreads=threads // 并发的线程数目,通常设为并行垃圾回收线程数的1/4(垃圾回收并发阶段)
最后
针对以上面试题,小编已经把面试题+答案整理好了
面试专题
除了以上面试题+答案,小编同时还整理了微服务相关的实战文档也可以分享给大家学习
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
3104786651)]
[外链图片转存中…(img-tuxhuwc0-1713104786651)]
面试专题
[外链图片转存中…(img-Vjus64G7-1713104786652)]
除了以上面试题+答案,小编同时还整理了微服务相关的实战文档也可以分享给大家学习
[外链图片转存中…(img-goJOgnKq-1713104786652)]
[外链图片转存中…(img-fcVVFNix-1713104786653)]
[外链图片转存中…(img-QgkspjKa-1713104786653)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-kAyXpNj7-1713104786653)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!