网易有道hr岗位面试,万字长文,Java开发者出路在哪

该段代码的GC调用过程如下:

万字长文,字节大牛百万调优经验之作:JVM调优实战笔记“上篇”

很明显,变量b由于a的作用被回收了。

同理,读者可以再阅读以下两个函数。函数test4()由于在变量b之前定义了变量c,故作用域外的变量a复用了变量c的字。变量b依然保留,因此GC操作无法回收变量b的空间。而在函数test5()中,由于后续又定义了变量a和变量d,恰好复用了变量c和变量b的字,故GC操作可以顺利回收变量b所占的空间。

//GC无法回收byte数组,因为变量a复用了c的字,b仍然存在publicstaticvoidtest4(){

{int c=0;

byte[]b=newbyte[612041024];}

int a=0; //复用c的字

System.gc();

System.out.println(“firstexplictgcover”);

}

publicstaticvoidtest5(){ //GC可以回收byte数组,因为变量d复用了b的字

{

int c=0;

byte[]b=newbyte[612041024];

}

int a=0; //复用c的字

int d=0; //复用b的字

System.gc();

System.out.println(“firstexplictgcover”);

}

在方法体内,变量b所在的字是否被复用,或者变量b是否被手工设置为null,当方法一结束,该方法的栈帧就会被销毁,即栈帧中的局部变量表也被销毁,变量b就会被自然回收。

publicstaticvoidmain(Stringargs[]){

test1();

System.gc(); //总是可以回收b,因为上层函数的栈帧已经销毁

System.out.println(“secondexplictgcover”);

}

以上代码先调用了test1(),虽然在test1()中变量b无法回收,但是当test1()方法一结束,其栈帧被销毁,那么方法体外的GC就能顺利回收变量b了。以上代码的GC调用过程如下:

[GC271K->151K(5056K),0.0014619 secs]

[FullGC151K->151K(5056K),0.0108332 secs]

[FullGC7375K->7375K(12284K),0.0097149 secs]

first explict gc over

[FullGC7394K->151K(13320K),0.0081832 secs]

second explict gc over

可以看到,方法体内的GC操作没能回收内存,但在test1()方法体外的GC操作成功回收了变量b。

注意:局部变量表中的字可能会影响GC回收。如果这个字没有被后续代码复用,那么它所引用的对象不会被GC释放。

本地方法栈

=====

本地方法栈和Java虚拟机栈的功能很相似,Java虚拟机栈用于管理Java函数的调用,而本地方法栈用于管理本地方法的调用。本地方法并不是用Java实现的,而是使用C语言实现的。在SUN的HotSpot虚拟机中,不区分本地方法栈和虚拟机栈,因此和虚拟机栈一样,它也会抛出StackOverflowError和OutOfMemoryError异常。

Java堆

Java堆可以说是Java运行时内存中最为重要的部分,几乎所有的对象和数组都是在堆中分配空间的。Java堆分为新生代和老年代两个部分。新生代用于存放刚刚产生的对象和年轻的对象,如果对象一直没有被回收,生存得足够长,则该对象就会被移入老年代。

新生代又可进一步细分为eden、survivorspace0(s0或者fromspace)和survivorspace1(s1或者tospace)。eden意为伊甸园,即对象的出生地,大部分对象刚刚建立时,通常会存放在这里。s0和s1为survivor空间,直译为幸存者,也就是说存放其中的对象至少经历了一次垃圾回收并得以幸存。如果在幸存区的对象到了指定年龄仍未被回收,则有机会进入老年代(tenured)。

注意:堆空间可以简单地分为新生代和老年代。新生代用于存放刚产生的新对象,老年代则存放年长的对象(存在的时间较长,经过垃圾回收的次数较多的对象)。

堆空间的基本结构如图5.5所示。

万字长文,字节大牛百万调优经验之作:JVM调优实战笔记“上篇”

为了方便读者更好地理解对象在内存中的分配方式,可以结合以下这个简单的示例,初步了解对象在堆中的分布。

publicclassTestHeapGC{

publicstaticvoidmain(Stringargs[]){

byte[] b1=new byte[1024*1024/2];

byte[] b2=newbyte[102410248];

b2=null;

b2=newbyte[102410248] ;//进行一次新生代GC调用

//System.gc();

}

}

使用JVM参数“-XX:+PrintGCDetails-XX:SurvivorRatio=8-XX:MaxTenuringThreshold=15-Xms40M-Xmx40M-Xmn20M”运行这段代码,输出结果如下:

万字长文,字节大牛百万调优经验之作:JVM调优实战笔记“上篇”

首先,在示例代码中注释掉显示GC的这一行代码。由程序的输出结果可以看到,在多次进行内存分配的过程中,触发了一次新生代GC。在这次GC调用中,原本分配在eden段的变量b1被移动到from空间段(s0)。最后分配的8MB内存被分配到eden新生代。如果执行程序中的FullGC操作,则堆的信息如下:

万字长文,字节大牛百万调优经验之作:JVM调优实战笔记“上篇”

可以看到,在执行FullGC操作之后,新生代空间被清空,未被回收的对象全部被移入老年代(tenured)。

JVM所使用的GC操作方式JVM调优的重点之一,这部分内容将在后续章节中详细介绍。

方法区

===

方法区也是JVM内存区中非常重要的一块内存区域。与堆空间类似,它也是被JVM中所有的线程共享的。方法区主要保存的信息是类的元数据。

方法区中最为重要的是类的类型信息、常量池、域信息和方法信息。类型信息包括类的完整名称、父类的完整名称、类型修饰符(public/protected/private)和类型的直接接口类表;常量池包括这个类方法、域等信息所引用的常量信息;域信息包括域名称、域类型和域修饰符;方法信息包括方法名称、返回类型、方法参数、方法修饰符、方法字节码、操作数栈和方法栈帧的局部变量区大小及异常表。总之,方法区内保存的信息大部分来自于class文件,是Java应用程序运行必不可少的重要数据。

在HotSpot虚拟机中,方法区也称之为永久区,是一块独立于Java堆的内存空间。虽然叫作永久区,但是在永久区中的对象同样也是可以被GC回收的,只是GC的表现和Java堆空间略有不同。对永久区GC的回收,通常主要从两个方面分析:一是GC对永久区常量池的回收;二是永久区对类元数据的回收。

注意:方法区也可称为永久区,主要存放常量及类的定义信息。

HotSpot虚拟机对常量池的回收策略是很明确的。只要常量池中的常量没有被任何地方引用,就可以被回收。下面的代码生成了大量的String对象,并将其加入常量池。String.intern()方法的含义是:如果常量池中已经存在当前String,则返回池中的对象;如果常量池中不存在当前String对象,则先将String加入常量池,并返回池中的对象引用。

因此,以下代码会不停地将String对象加入常量池,导致永久区饱和。如果GC不能回收永久区的这些常量数据,那么就会抛出OutOfMemory错误。

@Test

public void permGenGC(){

for (int i=0; i < Integer.MAX_VALUE; i++){

String t=String.valueOf(i).intern(); //加入常量池

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总结

如果你选择了IT行业并坚定的走下去,这个方向肯定是没有一丝问题的,这是个高薪行业,但是高薪是凭自己的努力学习获取来的,这次我把P8大佬用过的一些学习笔记(pdf)都整理在本文中了

《Java中高级核心知识全面解析》

小米商场项目实战,别再担心面试没有实战项目:

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值