知识大全 怎样用Jvm处理Java数组

Posted 变量

篇首语:追风赶月莫停留,平芜尽处是春山。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 怎样用Jvm处理Java数组相关的知识,希望对你有一定的参考价值。

怎样用Jvm处理Java数组  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  记得vamcily 曾问我 为什么获取数组的长度用 length(成员变量的形式) 而获取String的长度用 length()(成员方法的形式)?

  我当时一听 觉得问得很有道理 做同样一件事情 为什么采用两种风格迥异的风格呢?况且 Java中的数组其实是完备(full fledged)的对象 直接暴露成员变量 可能不是一种很OO的风格 那么 设计Java的那帮天才为什么这么做呢?

  带着这个疑问 我查阅了一些资料 主要是关于 JVM是如何处理数组 的

  数组对象的类是什么?

  既然数组都是对象 那么数组的类究竟是什么呢?当然不是java util Arrays啦!我们以int一维数组为例 看看究竟

  public class Main

  public static void main(String args[])

  int a[] = new int[ ]; Class clazz = a getClass();

  System out println(clazz getName());

  

  

  在SUN JDK 上运行上述代码 输出为

  [I

  看起来数组的类很奇怪 非但不属于任何包 而且名称还不是合法的标识符(identifier) 具体的命名规则[ ]可以参见 java lang Class getName()的javadoc 简单的说 数组的类名由若干个 [ 和数组元素类型的内部名称组成 [ 的数目 代表了数组的维度

  具有相同类型元素和相同维度的数组 属于同一个类 如果两个数组的元素类型相同 但维度不同 那么它们也属于不同的类 如果两个数组的元素类型 和维度均相同 但长度不同 那么它们还是属于同一个类

  数组的类有哪些成员呢?

  既然我们知道了数组的类名是什么 那么就去看看数组的类究竟是什么样的吧?有哪些成员变量?有哪些成员方法?length这个成员变量在哪?是 不是没有length()这个成员方法?

  找来找去 在JDK的代码中没有找打 [I 这个类 想想也对 [I 都不是一个合法的标识符 肯定不会出现public class [I 这样的Java代码 我们暂且不管[I类是谁声明的 怎么声明的 先用反射机制一探究竟吧

  public class Main

  public static void main(String[] args)

  int a[] = new int[ ]; Class clazz = a getClass();

  System out println(clazz getDeclaredFields() length);

  System out println(clazz getDeclaredMethods() length);

  System out println(clazz getDeclaredConstructors() length);

  System out println(clazz getDeclaredAnnotations() length);

  System out println(clazz getDeclaredClasses() length);

  System out println(clazz getSuperclass());

  

  

  在SUN JDK 上运行上述代码 输出为

   class java lang Object   可见 [I这个类是java lang Object的直接子类 自身没有声明任何成员变量 成员方法 构造函数和Annotation 可以说 [I就 是个空类 我们立马可以想到一个问题 怎么连length这个成员变量都没有呢?如果真的没有 编译器怎么不报语法错呢?想必编译器对 Array length进行了特殊处理哇!

  数组的类在哪里声明的?

  先不管为什么没有length成员变量 我们先搞清楚[I这个类是哪里声明的吧 既然[I都不是合法的标识符 那么这个类肯定在Java代码中 显式声明的 想来想去 只能是JVM自己在运行时生成的了 JVM生成类还是一件很容易的事情 甚至无需生成字节码 直接在方法区中创建类型数据 就差不 多完工了

  还没有实力去看JVM的源代码 于是翻了翻The JavaTM Virtual Machine Specification  Second Edition 果然得到了验证 相关内容参考 Creating Array Classes

  规范的描述很严谨 还掺杂了定义类加载器和初始化类加载器的内容 先不管这些 简单概括一下

  类加载器先看看数组类是否已经被创建了 如果没有 那就说明需要创建数组类 如果有 那就无需创建了

  如果数组元素是引用类型 那么类加载器首先去加载数组元素的类

  JVM根据元素类型和维度 创建相应的数组类

  呵呵 果然是JVM这家伙自个偷偷创建了[I类 JVM不把数组类放到任何包中 也不给他们起个合法的标识符名称 估计是为了避免和JDK 第 三方及用户自定义的类发生冲突吧

  再想想 JVM也必须动态生成数组类 因为Java数组类的数量与元素类型 维度(最多 )有关 相当相当多了 是没法预先声明好的

  居然没有length这个成员变量!

  我们已经发现 偷懒的JVM没有为数组类生成length这个成员变量 那么Array length这样的语法如何通过编译 如何执行的呢?

  让我们看看字节码吧!编写一段最简单的代码 使用jclasslib查看字节码

  public class Main

  public static void main(String[] args)  

  int a[] = new int[ ]; int i = a length;

  

  

  使用SUN JDK 编译上述代码 并使用jclasslib打开Main class文件 得到main方法的字节码

   iconst_                    //将int型常量 压入操作数栈  newarray (int)    //将 弹出操作数栈 作为长度 创建一个元素类型为int 维度为 的数组 并将数组的引用压入操作数栈  astore_                  //将数组的引用从操作数栈中弹出 保存在索引为 的局部变量(即a)中  aload_                   //将索引为 的局部变量(即a)压入操作数栈  arraylength            //从操作数栈弹出数组引用(即a) 并获取其长度(JVM负责实现如何获取) 并将长度压入操作数栈  istore_                  //将数组长度从操作数栈弹出 保存在索引为 的局部变量(即i)中  return                    //main方法返回   可见 在这段字节码中 根本就没有看见length这个成员变量 获取数组长度是由一条特定的指令arraylength实现(怎么实现就不管了 JVM 总有办法) 编译器对Array length这样的语法做了特殊处理 直接编译成了arraylength指令 另外 JVM创建数组类 应该就是由 newarray这条指令触发的了

  很自然地想到 编译器也可以对Array length()这样的语法做特殊处理 直接编译成arraylength指令 这样的话 我们就可 以使用方法调用的风格获取数组的长度了 这样看起来貌似也更加OO一点 那为什么不使用Array length()的语法呢?也许是开发Java的那帮 天才对 length有所偏爱 或者抛硬币拍脑袋随便决定的吧 形式不重要 重要的是我们明白了背后的机理

  Array in Java

  最后 对Java中纯对象的数组发表点感想吧

  相比C/C++中的数组 Java数组在安全性要好很多 C/C++常遇到的缓存区溢出或数组访问越界的问题 在Java中不再存在 因为 Java使用特定的指令访问数组的元素 这些指令都会对数组的长度进行检查 如果发现越界 就会抛出 java lang ArrayIndexOutOfBoundsException

cha138/Article/program/Java/hx/201311/25592

相关参考

知识大全 Java程序性能优化-JVM调优

Java程序性能优化-JVM调优  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!   JV

知识大全 java 整形数组、字节流的互转

  前言  某些时候我们想存储一些整形长整形的内容到一些地方当然你可能会用分隔来存比如    这种形式并没有错但存以几个缺点  字符串格式占用空间太多在java里以上字符串至少条占*=Byte不管是读

知识大全 设置Java虚拟机(JVM)的内存问题

设置Java虚拟机(JVM)的内存问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &

知识大全 关于 java.exe 是如何载入 JVM

关于java.exe是如何载入JVM  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  将会生成如下

知识大全 关于设置Java虚拟机(JVM)的内存问题

关于设置Java虚拟机(JVM)的内存问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  最近做

知识大全 JAVA文件编译执行与虚拟机(JVM)介绍

JAVA文件编译执行与虚拟机(JVM)介绍  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Jav

知识大全 Java多线程同步如何从JVM的角度体会

Java多线程同步如何从JVM的角度体会  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  我们在使

知识大全 64位计算中的Java虚拟机(JVM)性能测试

64位计算中的Java虚拟机(JVM)性能测试  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  随

知识大全 探索Java语言与JVM中的Lambda表达式

探索Java语言与JVM中的Lambda表达式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  L

知识大全 java源代码分析----jvm.dll装载过程

  简述    众所周知javaexe是javaclass文件的执行程序但实际上javaexe程序只是  一个执行的外壳它会装载jvmdll(windows下以下皆以windows平台为例  linu