astore

工作10年后,再看String s = new String("xyz") 创建了几个对象?

半世苍凉 提交于 2021-02-19 02:57:15
点击上方蓝色“ 方志朋 ”,选择“设为星标” 回复“ 666 ”获取独家整理的学习资料! 转自:艾小仙 这个问题相信每个学习java的同学都不陌生,作为一个经典的面试题,到现在工作这么多年了我真是认为挺操蛋的一个问题,在网上到现在你仍然可以看见很多讨论这个问题的人,其中不乏工作很多年的人都有争论,我认为还是有必要来说一说这个问题的。 从方法区说起 常量池存在于方法区,而方法区在jdk1.7版本前后改变比较大,所以还是先来说说方法区的演变。 在jdk1.7版本之前,常量池存在于方法区,方法区是堆的一个逻辑部分,他有一个名字叫做 非堆 。 1.7版本把字符串常量池放到了堆中。 而在1.8以后,则是移除了永久代,方法区概念保留,方法区的实现改为了元空间,常量池还是在堆中。 为什么要说方法区的改变,只是为了文章接下来的内容不会由于JDK的版本而产生分歧,接下来内容都会以jdk1.8版本作为基础来讨论。 String s = new String("xyz"); 先来一段代码 public class Test { public static void main (String[] args) { String s = "xyz" ; } } 接着我们javac编译代码,然后用javap来反编译,执行javap -c Test 从结果来看,ldc命令 在常量池中创建了一个"xyz"的对象

工作10年后,再看String s = new String("xyz") 创建了几个对象?

梦想的初衷 提交于 2021-02-19 02:28:03
点击上方 " 程序员小乐 "关注, 星标或置顶一起成长 后台回复“ 大礼包 ”有惊喜礼包! 关注订阅号「 程序员小乐 」,收看更多精彩内容 每日英文 When a person cannot answer directly to ur question, probably the answer is too painful for you to know or too hard for them to admit. 如果一个人不正面回答你的问题,可能是说出来你难以接受,或者他们不愿意承认。 每日掏心话 一生中,最光辉的一天并非功成名就的那一天,而是从悲叹与绝望中产生对人生挑战与勇敢迈向意志的那一天。 来 自 :艾小仙 | 责编:乐乐 后端架构师(ID:study_tech) 第 1085 次推文 往日回顾: 2020 中国软件 100 强,腾讯第二、阿里第三,他第一! 正文 这个问题相信每个学习java的同学都不陌生,作为一个经典的面试题,到现在工作这么多年了我真是认为挺操蛋的一个问题,在网上到现在你仍然可以看见很多讨论这个问题的人,其中不乏工作很多年的人都有争论,我认为还是有必要来说一说这个问题的。 从方法区说起 常量池存在于方法区,而方法区在jdk1.7版本前后改变比较大,所以还是先来说说方法区的演变。 在jdk1.7版本之前,常量池存在于方法区,方法区是堆的一个逻辑部分

Java中try catch finally的执行顺序问题

跟風遠走 提交于 2021-02-13 03:55:59
finally 语句块是在 try 或者 catch 中的 return 语句之前执行的。更加一般的说法是,finally 语句块应该是在控制转移语句之前执行,控制转移语句除了 return 外,还有 break 和 continue。另外,throw 语句也属于控制转移语句。虽然 return、throw、break 和 continue 都是控制转移语句,但是它们之间是有区别的。其中 return 和 throw 把程序控制权转交给它们的调用者(invoker),而 break 和 continue 的控制权是在当前方法内转移。 关于 Java 虚拟机是如何编译 finally 语句块的问题,有兴趣的读者可以参考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 节 Compiling finally。那里详细介绍了 Java 虚拟机是如何编译 finally 语句块。实际上,Java 虚拟机会把 finally 语句块作为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,免得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally

《深入理解Java虚拟机》- JVM是如何实现反射的

邮差的信 提交于 2021-02-07 06:46:09
Java反射学问很深,这里就浅谈吧。如果涉及到方法内联,逃逸分析的话,我们就说说是什么就好了。有兴趣的可以去另外看看,我后面可能也会写一下。(因为我也不会呀~) 一、Java反射是什么? 反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。 反射是由类开始的,从class对象中,我们可以获得有关该类的全部成员的完整列表;可以找出该类的所有类型、类自身信息。 二、反射的一些应用 1、java集成开发环境,每当我们敲入点号时,IDE便会根据点号前的内容,动态展示可以访问的字段和方法。 2、java调试器,它能够在调试过程中枚举某一对象所有字段的值。 3、web开发中,我们经常接触到各种配置的通用框架。为保证框架的可扩展性,他往往借助java的反射机制。例如Spring框架的依赖反转(IOC)便是依赖于反射机制。 三、Java反射的实现 1. Java反射使用的api(列举部分,具体在rt.jar包的java.lang.reflect.*)中 列举Class.java中的一些方法。这些都很常用,比如在你尝试编写一个mvc框架的时候,就可以参照这个类里面的方法,再结合一些Servlet的api就实现一个简单的框架。 2.代码实现 2.1 代码实现的目的:说明反射调用是有两种方式,一种是本地实现,另一种是委派实现。

字节码角度分析异常处理【try-catch-finally】

有些话、适合烂在心里 提交于 2021-01-28 20:07:33
研究背景: 最近在仔仔细细学习公司的一些项目代码,包含很多模块下的Utils类的阅读,因为在我看来工具类中的绝大部分方法都可以在特定场合下被很多地方调用,那么他的编写可以说是这个模块的精髓代码! 但是发现不少关于try-catch-finally的使用甚至嵌套处理,关于try-catch-finally中return的写法网上也是众说纷纭,记得之前研究JVM底层的时候有涉及过这方面的知识点,但当时没有把这个作为重点去纪录。今天特意拿出来研究研究,探讨一番! 研究主题 try-catch-finally的异常处理机制以及返回语句return的编写时机 研究角度 本篇文章我们主要以Java字节码的角度为主Oracle官方文档为辅去权威的理解一下关于异常处理的相关问题 相关环境 我们针对JDK1.8的HotSpot VM虚拟机做讨论 因为在JVM规范约束下,主流选择有:(按流行程度递减) 1. HotSpot VM 2. J9 VM 3. Zing VM 进入正题 先来一段示例代码去简单分析一下 public static void main(String[] args) { int i = 0; try { i = 10; } catch (Exception e) { i = 20; } } 简单的try catch 语句返回一个int变量,当然我们这段代码是不会有异常的

JVM指令手册

℡╲_俬逩灬. 提交于 2021-01-09 20:42:03
栈和局部变量操作 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 iconst_1 将int类型常量1压入栈 iconst_2 将int类型常量2压入栈 iconst_3 将int类型常量3压入栈 iconst_4 将int类型常量4压入栈 iconst_5 将int类型常量5压入栈 lconst_0 将long类型常量0压入栈 lconst_1 将long类型常量1压入栈 fconst_0 将float类型常量0压入栈 fconst_1 将float类型常量1压入栈 dconst_0 将double类型常量0压入栈 dconst_1 将double类型常量1压入栈 bipush 将一个8位带符号整数压入栈 sipush 将16位带符号整数压入栈 ldc 把常量池中的项压入栈 ldc_w 把常量池中的项压入栈(使用宽索引) ldc2_w 把常量池中long类型或者double类型的项压入栈(使用宽索引) 从栈中的局部变量中装载值的指令 iload 从局部变量中装载int类型值 lload 从局部变量中装载long类型值 fload 从局部变量中装载float类型值 dload 从局部变量中装载double类型值 aload 从局部变量中装载引用类型值(refernce)

JVM指令手册

爷,独闯天下 提交于 2021-01-09 20:41:40
可以使用javap -c t.class > t.txt 命令将class文件输出到txt文档来结合以下指令分析代码。 栈和局部变量操作 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 iconst_1 将int类型常量1压入操作数栈 iconst_2 将int类型常量2压入栈 iconst_3 将int类型常量3压入栈 iconst_4 将int类型常量4压入栈 iconst_5 将int类型常量5压入栈 lconst_0 将long类型常量0压入栈 lconst_1 将long类型常量1压入栈 fconst_0 将float类型常量0压入栈 fconst_1 将float类型常量1压入栈 dconst_0 将double类型常量0压入栈 dconst_1 将double类型常量1压入栈 bipush 将一个8位带符号整数压入栈 sipush 将16位带符号整数压入栈 ldc 把常量池中的项压入栈 ldc_w 把常量池中的项压入栈(使用宽索引) ldc2_w 把常量池中long类型或者double类型的项压入栈(使用宽索引) 从栈中的局部变量中装载值的指令 iload 从局部变量中装载int类型值 lload 从局部变量中装载long类型值 fload

深入JVM(一)JVM指令手册

爷,独闯天下 提交于 2021-01-09 18:05:20
本文按照如下思维导图组织 1. 栈和局部变量操作 1.1 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 iconst_1 将int类型常量1压入栈 iconst_2 将int类型常量2压入栈 iconst_3 将int类型常量3压入栈 iconst_4 将int类型常量4压入栈 iconst_5 将int类型常量5压入栈 lconst_0 将long类型常量0压入栈 lconst_1 将long类型常量1压入栈 fconst_0 将float类型常量0压入栈 fconst_1 将float类型常量1压入栈 dconst_0 将double类型常量0压入栈 dconst_1 将double类型常量1压入栈 bipush 将一个8位带符号整数压入栈 sipush 将16位带符号整数压入栈 ldc 把常量池中的项压入栈 ldc_w 把常量池中的项压入栈(使用宽索引) ldc2_w 把常量池中long类型或者double类型的项压入栈(使用宽索引) 1.2 从栈中的局部变量中装载值的指令 iload 从局部变量中装载int类型值 lload 从局部变量中装载long类型值 fload 从局部变量中装载float类型值 dload 从局部变量中装载double类型值 aload

java 泛型的内部原理:类型擦除以及类型擦除带来的问题

笑着哭i 提交于 2020-12-21 04:57:57
一、Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型。为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦出(type erasure)。 Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。 如在代码中定义的List<object>和List<String>等类型,在编译后都会编程List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方法与C++模版机制实现方式之间的重要区别。 可以通过两个简单的例子,来证明java泛型的类型擦除。 例1、 public class Test4 { public static void main(String[] args) { ArrayList <String> arrayList1= new ArrayList<String> (); arrayList1.add( "abc" ); ArrayList <Integer> arrayList2= new

Java 中 String 对 null 对象的容错处理!

十年热恋 提交于 2020-10-14 23:04:38
作者:肖汉松 blog.xiaohansong.com/2016/03/13/null-in-java-string/ 最近在读《Thinking in Java》,看到这样一段话: _Primitives that are fields in a class are automatically initialized to zero, as noted in the Everything Is an Object chapter. _ _But the object references are initialized to null, and if you try to call methods for any of them, you’ll get an exception-a runtime error. _ Conveniently, you can still print a null reference without throwing an exception. 大意是:原生类型会被自动初始化为 0,但是对象引用会被初始化为 null,如果你尝试调用该对象的方法,就会抛出空指针异常。通常,你可以打印一个 null 对象而不会抛出异常。 第一句相信大家都会容易理解,这是类型初始化的基础知识,但是第二句就让我很疑惑:为什么打印一个 null 对象不会抛出异常