- 浏览: 469967 次
- 性别:
- 来自: 杭州
-
文章分类
- 全部博客 (146)
- Maven (3)
- Quartz (10)
- Hessian (3)
- JDK (42)
- eclipse (4)
- 设计思想 (6)
- XML (8)
- JavaMail (1)
- Spring (11)
- mina (1)
- HsqlDb (1)
- Cache (2)
- Tool (6)
- 心情 (5)
- JQuery (0)
- Hadoop (5)
- Hbase (3)
- 自动构建 (7)
- JNDI (0)
- 代码赏析 (5)
- Oracle (1)
- Excel (4)
- Effective Java (5)
- JAXB (4)
- fdafasdf (1)
- ccc (0)
- web (3)
- concurrent (1)
- CVS (1)
- eclipse plugin (2)
- Apache (10)
最新评论
-
chxiaowu:
nice!
Quartz实现固定执行次数 -
zxjlwt:
学习了。http://surenpi.com
自定义ClassLoader -
kadlly:
public static final Logger log ...
Hessian 权限认证 -
spring_springmvc:
java程序语言学习教程 地址http://www.zuida ...
Java-Final -
liushuiwuyan:
[img][/img]
设计模式-单例
Java代码如下,很简单.
返回的是什么,为什么。
另一种方式如下.
解析java代码为class文件,再执行JVM指令执行程序。看这个比较容易理解JVM的处理规则,其实也能更深刻的理解对象引用和值引用.
第二种情况,最后Integer先执行操作运行,这个操作会把Integer转化为int,然后再执行计算,最后再执行==操作,因为全转化为常量了,所以相等了。
JVM运行时数据区的内存模型由五部分组成
(1)方法区
(2)堆
(3)JAVA栈
(4)PC寄存器
(5)本地方法栈
对于String s = "haha" ,它的虚拟机指令
0: ldc "16; //String haha 2: astore_1 3: return
JVM常量池
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM常量池在内存当中是以表的形式存在的,对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。说到这里,对JVM常量池中的字符串值的存储位置应该有一个比较明了的理解了。
在介绍完JVM常量池的概念后,接着谈开始提到的"haha"的值的内存分布的位置。对于haha的值,实际上是在class文件被JVM装载到内存当中并被引擎在解析ldc指令并执行ldc指令之前,JVM就已经为haha这个字符串在常量池的CONSTANT_String_info表中分配了空间来存储haha这个值。
既然haha这个字符串常量存储在常量池中,常量池是属于类型信息的一部分,类型信息也就是每一个被的类型,这个类型反映到JVM内存模型中是对应存在于JVM内存模型的方法区中,也就是这个类型信息中的JVM常量池概念是存在于在方法区中,而方法区是在JVM内存模型中的堆中由JVM来分配的。所以,haha的值是应该是存在堆空间中的。而对于String s = new String("haha") ,它的JVM指令
new指令过程:
要执行new指令,Jvm通过计算(indextype1<<8)|indextype2生成一个指向常量池的无符号16位索引。然后JVM根据计算出的索引查找JVM常量池入口。该索引所指向的常量池入口必须为CONSTANT_Class_info。如果该入口尚不存在,那么JVM将解析这个常量池入口,该入口类型必须是类。JVM从堆中为新对象映像分配足够大的空间,并将对象的实例变量设为默认值。最后JVM将指向新对象的引用objectref压入操作数栈。
dup指令过程:
要执行dup指令,JVM复制了操作数栈顶部一个字长的内容,然后再将复制内容压入栈。本指令能够从操作数栈顶部复制任何单位字长的值。但绝对不要使用它来复制操作数栈顶部任何两个字长(long型或double型)中的一个字长。上面例中,即复制引用objectref,这时在操作数栈存在2个引用。
ldc指令过程:
要执行ldc指令,JVM首先查找index所指定的常量池入口,在index指向的JVM常量池入口,JVM将会查找CONSTANT_Integer_info,CONSTANT_Float_info和CONSTANT_String_info入口。如果还没有这些入口,JVM会解析它们。而对于上面的haha,JVM会找到CONSTANT_String_info入口,将把指向被拘留String对象(由解析该入口的进程产生)的引用压入操作数栈。
Invokespecial指令
invokespecial指令过程:对于该类而言,该指令是用来进行实例初始化方法的调用。上面例子中,即通过其中一个引用调用String类的构造器,初始化对象实例,让另一个相同的引用指向这个被初始化的对象实例,然后前一个引用弹出操作数栈。
astore_1指令过程:
要执行astore_1指令,JVM从操作数栈顶部弹出一个引用类型或者returnAddress类型值,然后将该值存入由索引1指定的局部变量中,即将引用类型或者returnAddress类型值存入局部变量1。
return 指令的过程:
从方法中返回,返回值为void,要执行astore_1指令,JVM从操作数栈顶部弹出一个引用类型或者returnAddress类型值,然后将该值存入由索引1指定的局部变量中,即将引用类型或者returnAddress类型值存入局部变量1。
package com.test.add; public class TestInteger { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Integer int1 = 30; Integer int2 = 30; Integer int3 = 0; System.out.println(int1 == int2); System.out.println(int1 == int2 + int3); } }
返回的是什么,为什么。
解析如下:主要进行了自动装包,valueOf.[1种] 自动解包 intValue()[2种] public static void main(java.lang.String[] args); 0 bipush 30 [将单字节的常量值(-128~127)推送至栈顶] 2 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [16][调用valueOf方法] 5 astore_1 [int1][ 将栈顶引用型数值存入指定本地变量] 6 bipush 30 8 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [16] 11 astore_2 [int2] 12 iconst_0[将int型0推送至栈顶] 13 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [16] 16 astore_3 [int3] 17 getstatic java.lang.System.out : java.io.PrintStream [22] 20 aload_1 [int1][ 将指定的引用类型本地变量推送至栈顶] 21 aload_2 [int2] 22 if_acmpne 29[比较栈顶两引用型数值,当结果不相等时跳转] 25 iconst_1[将int型1推送至栈顶] 26 goto 30[无条件跳转] 29 iconst_0[将int型0推送至栈顶] 30 invokevirtual java.io.PrintStream.println(boolean) : void [28] 33 getstatic java.lang.System.out : java.io.PrintStream [22] 36 aload_1 [int1] 37 invokevirtual java.lang.Integer.intValue() : int [34] [调用intValue方法] 40 aload_2 [int2] 41 invokevirtual java.lang.Integer.intValue() : int [34] 44 aload_3 [int3] 45 invokevirtual java.lang.Integer.intValue() : int [34] 48 iadd[将栈顶两int型数值相加并将结果压入栈顶] 49 if_icmpne 56[比较栈顶两引用型数值,当结果不相等时跳转] 52 iconst_1 53 goto 57 56 iconst_0 57 invokevirtual java.io.PrintStream.println(boolean) : void [28] 60 return }
另一种方式如下.
package com.test.add; public class TestInteger2 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Integer int4 = new Integer(30); Integer int5 = new Integer(30); Integer int6 = new Integer(0); System.out.println(int4 == int5); System.out.println(int4 == int5 + int6); } }
public static void main(java.lang.String[] args); 0 new java.lang.Integer [16][创建一个新的对象并分配内存,堆] 3 dup[复制栈顶数值并将复制值压入栈顶,栈] 4 bipush 30 [将单字节的常量值(-128~127)推送至栈顶] 6 invokespecial java.lang.Integer(int) [18] 9 astore_1 [int4] [ 将栈顶引用型数值存入指定本地变量] 10 new java.lang.Integer [16] 13 dup 14 bipush 30 16 invokespecial java.lang.Integer(int) [18] 19 astore_2 [int5] 20 new java.lang.Integer [16] 23 dup 24 iconst_0 25 invokespecial java.lang.Integer(int) [18] 28 astore_3 [int6] 29 getstatic java.lang.System.out : java.io.PrintStream [21] 32 aload_1 [int4] 33 aload_2 [int5] 34 if_acmpne 41[两个新的内存地址进行比较] 37 iconst_1 38 goto 42 41 iconst_0 42 invokevirtual java.io.PrintStream.println(boolean) : void [27] 45 getstatic java.lang.System.out : java.io.PrintStream [21] 48 aload_1 [int4] 49 invokevirtual java.lang.Integer.intValue() : int [33] 52 aload_2 [int5] 53 invokevirtual java.lang.Integer.intValue() : int [33] 56 aload_3 [int6] 57 invokevirtual java.lang.Integer.intValue() : int [33] 60 iadd 61 if_icmpne 68[比较的是intValue值] 64 iconst_1 65 goto 69 68 iconst_0 69 invokevirtual java.io.PrintStream.println(boolean) : void [27] 72 return
解析java代码为class文件,再执行JVM指令执行程序。看这个比较容易理解JVM的处理规则,其实也能更深刻的理解对象引用和值引用.
第二种情况,最后Integer先执行操作运行,这个操作会把Integer转化为int,然后再执行计算,最后再执行==操作,因为全转化为常量了,所以相等了。
JVM运行时数据区的内存模型由五部分组成
(1)方法区
(2)堆
(3)JAVA栈
(4)PC寄存器
(5)本地方法栈
对于String s = "haha" ,它的虚拟机指令
0: ldc "16; //String haha 2: astore_1 3: return
JVM常量池
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM常量池在内存当中是以表的形式存在的,对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。说到这里,对JVM常量池中的字符串值的存储位置应该有一个比较明了的理解了。
在介绍完JVM常量池的概念后,接着谈开始提到的"haha"的值的内存分布的位置。对于haha的值,实际上是在class文件被JVM装载到内存当中并被引擎在解析ldc指令并执行ldc指令之前,JVM就已经为haha这个字符串在常量池的CONSTANT_String_info表中分配了空间来存储haha这个值。
既然haha这个字符串常量存储在常量池中,常量池是属于类型信息的一部分,类型信息也就是每一个被的类型,这个类型反映到JVM内存模型中是对应存在于JVM内存模型的方法区中,也就是这个类型信息中的JVM常量池概念是存在于在方法区中,而方法区是在JVM内存模型中的堆中由JVM来分配的。所以,haha的值是应该是存在堆空间中的。而对于String s = new String("haha") ,它的JVM指令
new指令过程:
要执行new指令,Jvm通过计算(indextype1<<8)|indextype2生成一个指向常量池的无符号16位索引。然后JVM根据计算出的索引查找JVM常量池入口。该索引所指向的常量池入口必须为CONSTANT_Class_info。如果该入口尚不存在,那么JVM将解析这个常量池入口,该入口类型必须是类。JVM从堆中为新对象映像分配足够大的空间,并将对象的实例变量设为默认值。最后JVM将指向新对象的引用objectref压入操作数栈。
dup指令过程:
要执行dup指令,JVM复制了操作数栈顶部一个字长的内容,然后再将复制内容压入栈。本指令能够从操作数栈顶部复制任何单位字长的值。但绝对不要使用它来复制操作数栈顶部任何两个字长(long型或double型)中的一个字长。上面例中,即复制引用objectref,这时在操作数栈存在2个引用。
ldc指令过程:
要执行ldc指令,JVM首先查找index所指定的常量池入口,在index指向的JVM常量池入口,JVM将会查找CONSTANT_Integer_info,CONSTANT_Float_info和CONSTANT_String_info入口。如果还没有这些入口,JVM会解析它们。而对于上面的haha,JVM会找到CONSTANT_String_info入口,将把指向被拘留String对象(由解析该入口的进程产生)的引用压入操作数栈。
Invokespecial指令
invokespecial指令过程:对于该类而言,该指令是用来进行实例初始化方法的调用。上面例子中,即通过其中一个引用调用String类的构造器,初始化对象实例,让另一个相同的引用指向这个被初始化的对象实例,然后前一个引用弹出操作数栈。
astore_1指令过程:
要执行astore_1指令,JVM从操作数栈顶部弹出一个引用类型或者returnAddress类型值,然后将该值存入由索引1指定的局部变量中,即将引用类型或者returnAddress类型值存入局部变量1。
return 指令的过程:
从方法中返回,返回值为void,要执行astore_1指令,JVM从操作数栈顶部弹出一个引用类型或者returnAddress类型值,然后将该值存入由索引1指定的局部变量中,即将引用类型或者returnAddress类型值存入局部变量1。
发表评论
-
Java Application Cache
2016-09-27 19:25 891Application Cache is used very ... -
Java 字符串分词
2015-01-02 14:43 1763在Java的世界里有个类型 ... -
jdk 1.6 新特性,集成Groovy, 性能很差
2014-04-02 14:27 1289性能都是相对的,如果调用量不是很大的话,可以忽略,毕竟使用为主 ... -
Fake Code easy implements
2014-04-01 15:41 1035package org.miniframe.modules ... -
JDK regex 用法及用途
2014-03-31 15:48 1227查找 Boolean flag = pattern.mat ... -
生产者消费者(四)
2014-03-04 12:32 1157需求: 多个生产者不断的生产产品,多个消费者不断的消费产品,仓 ... -
生产者消费者(三)
2014-03-04 10:59 968需求: 多个生产者不断的生产产品,多个消费者不断的消费产品,仓 ... -
生产者消费者(二)
2014-03-03 15:40 701需求: 多个生产者不断的生产产品,多个消费者不断的消费产品,仓 ... -
生产者消费者模式(一)
2014-02-28 14:30 1038需求: 多个生产者不断的生产产品,多个消费者不断的消费产品,仓 ... -
查看Class文件使用的JDK版本
2013-10-30 14:17 1123由于JDK一般是向下兼容的,所以有时候本地的JDK版本比类库的 ... -
Java源代码转码
2012-12-20 17:22 1329现在中国的项目很多,编码无非是UTF-8,GBK,GB2312 ... -
Tomcat集成OSGI,并通过JNDI开放Web调用
2012-12-03 11:22 3150Tomcat集成OSGi,首先要选择OSGI服务器,我这里采用 ... -
JDK的Logging
2012-11-07 15:49 1690jdk自带有一个log日志,对于一般的使用,仅够了. 代码如下 ... -
java.util.*
2012-11-06 14:23 1384java.util 工具包,灰常的有用,有机会一定要研读源码。 ... -
java.util.concurrent.*
2012-11-02 10:38 17831. java.util.concurrent.ArrayBl ... -
java.util.rt.*
2012-10-31 13:51 11211. java.util.HashMap 散列表,主要是以离散 ... -
巧秒设计方法,不返回null
2016-09-27 19:32 743/** * {@inheritDoc} * ... -
java doc 代码文档
2012-07-13 13:58 1339对于代码规范不解释了,网上很多。 在编写代码的时候,有一点灰 ... -
接口与抽象类
2012-07-11 16:53 11301. 接口设计必谨慎,除非业务变更,否则打死不能动接口。[不变 ... -
JVM优化机制好诡异
2012-04-20 08:43 1476long i[] = new long[1000000]; ...
相关推荐
在 Java 中,Integer 对象在 -128 到 127 之间的值是缓存的,这意味着在这个范围内的所有 Integer 对象都是同一个对象引用。因此,当我们创建两个 Integer 对象,并将它们的值设置在这个范围内时,它们将引用的是同...
Python中的is和==比较两个对象的两种方法 在Python中有两种方式比较两个对象是否相等,分别是is和==,两者之间是不同的 ==比较的是值(如同java中的equals方法) is比较的是引用(可以看作比较内存地址, 类似于java中...
### 值引用与对象引用 #### 一、引言 在编程中,变量的引用方式分为两大类:值引用(Value Reference)和对象引用(Object Reference)。这两种引用方式决定了程序如何处理数据以及数据的存储方式。理解这些概念...
在Java编程语言中,理解对象和对象引用之间的关系是非常重要的基础。对象是类的一个实例,而对象引用则是用于访问该对象的一种手段。下面将详细探讨这两个概念。 #### 二、对象的创建过程 在Java中,当我们创建一...
### Java中对象与引用 在Java编程中,深入理解对象与引用的概念对于掌握面向对象编程至关重要。本文将从以下几个方面详细解析对象与引用的基本概念及其相互间的关系。 #### 一、对象与引用的基础概念 **对象**: ...
### Java中对象与对象引用的区别 #### 基础概念 在Java编程语言中,对象与对象引用是非常基础且重要的概念。理解它们之间的区别对于掌握Java面向对象编程至关重要。 #### 对象与引用定义 - **对象**:在Java中,...
对于引用类型,`==` 比较的是两个引用是否指向堆内存中的同一个对象实例。 2. `equals()` 方法: `equals()` 是Object类的一个方法,它的默认行为是与`==`一样,比较对象的引用。然而,很多类(如String、Integer...
Java中的`==`和`equals`方法都是比较对象的方法,但是它们的比较方式不同。`==`运算符比较引用地址,而`equals`方法比较对象的实际内容。在编程中,应该根据实际情况选择合适的比较方法,以避免错误的结果。
对于值类型,`==` 运算符和 `equals` 方法都是比较值的大小,而对于引用类型,`==` 运算符比较的是引用是否相同,而 `equals` 方法比较的是值是否相同。 例如: ```csharp int a = 5; int b = 5; bool result1 = a...
在实际中,使用对象引用作函数参数要比使用对象指针作函数更普遍,这是因为使用对象引用作函数参数具有用对象指针作函数参数的优点,而用对象引用作函数参数将更简单,更直接。所以,在C++编程中,人们喜欢用对象...
== 的作用是比较两个变量的值是否相等,但其比较规则根据变量的类型而不同。 (1) 基本数据类型 当 == 两边为基本数据类型时,== 判断的是两边变量中存放的内容是否相等。例如: ```java public class Test { ...
其次,equals 方法是一个对象比较的方法,它是用来比较两个对象的内容是否相同,而不是比较它们的内存地址。默认情况下,equals 方法都是调用 Object 类的 equals 方法,而 Object 的 equals 方法主要用于判断对象的...
### 对象与引用之间的概念 #### 一、引言 在C++等面向对象编程语言中,理解对象与引用之间的关系对于深入掌握面向对象技术至关重要。本文将详细探讨这一概念,帮助初学者清晰地区分对象与引用的区别。 #### 二、...
在Java编程语言中,深入理解和熟练运用引用、`this`关键字以及对象比较是提升编程技能的关键环节。本课程“MLDN魔乐JAVA_09深入引用、this关键字、对象比较”将带你深入探讨这些核心概念。 首先,让我们来讨论...
`==`运算符用于比较基本类型(如int,char)的值是否相等,对于引用类型,`==`比较的是两个引用是否指向内存中的同一个对象。而`equals()`方法则是对象的比较方法,通常重写自`Object`类,用于比较对象的内容是否...
问题1的答案就在于此:`==`比较的是对象引用,而`equals()`比较的是对象的内容或值。对于非字符串对象,如果它们的值相等,但不是同一个实例,`equals()`会返回真,而`==`会返回假。对于字符串,由于`equals()`被...
但对于引用类型,`==`比较的是两个变量所指向的堆中对象的地址,也就是说,它检查两个引用是否指向同一个对象实例。如果两个引用都指向堆中的同一个对象,`==`返回`true`,否则返回`false`。 `equals()`方法则是...
### 父类引用指向子类对象 在面向对象编程中,“父类引用指向子类对象”是一个重要的概念,尤其在Java等支持继承的语言中应用广泛。这一机制允许使用父类类型的引用变量来引用子类的对象,从而实现多态性。 #### ...
### 对象引用与对象的区别 在Java编程语言中,理解对象和对象引用之间的区别是非常重要的。这不仅是初学者经常会遇到的难点,也是深入学习面向对象编程的基础。 #### 对象的概念 对象是Java程序中的基本运行时...