java数据类型及其内存分配_第1页
java数据类型及其内存分配_第2页
java数据类型及其内存分配_第3页
java数据类型及其内存分配_第4页
java数据类型及其内存分配_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java数据类型及其在内存存放的位置Java数据类型基本类型(primitive)引用类型(reference)数值型整数类型(byteshortintlong)浮点类型(floatdouble)字符型(char)布尔类型(boolean)类(class)接口(interface)数组(array)类型名称占用存储空间表数范围默认值byte字节8bit(即1个字节)-128~127(-2^7~2^7-1)0short短整型16bit(即2个字节)-32768~32717(-2^15~2^15-1)0int整型32bit(即4个字节)-2^31~2^31-10long长整型64bit(即8个字节)-2^63~2^63-10Lfloat单精度浮点型32bit(即4个字节)-3.40E38~+3.40E380.0fdouble双精度浮点型64bit(即8个字节)-1.79E308~1.79E3080.0dchar字符型16bit(即2个字节)0~65535‘\u0000’(空)boolean布尔类型8bit(即1个字节)true,falsefalseJava基本数据类型(8种)基本数据类型packagetest01;publicclasstest1{publicstaticvoidmain(String[]args){inti=1;Intj=1;charch=“a“;System.out.println(i);System.out.println(ch);}栈1aij引用数据类型packagetest01;publicclasstest2{publicstaticvoidmain(String[]args){test2t2=newtest2();intreasult=t2.Rectangle(7,2020);System.out.println(reasult);}publicintRectangle(intwidth,intheight){ints=width*height;returns;}};栈堆newtest2()对象常量池110925t2对象的引用(引用变量的值为对象在堆中的首地址)packagetest01;importjava.util.ArrayList;publicclasstest2{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubint[]arr=newint[]{1,2};System.out.println(arr);ArrayList<Integer>arrayList=newArrayList<Integer>();arrayList.add(1);arrayList.add(2);System.out.println(arrayList);}};354725354720arrarrayList常量池1212packagetest01;publicclasstest3{publicstaticvoidmain(String[]args){Stringstr1="abc";Stringstr2="abc";Stringstr3=“bc”;Stringstr4=“def”;Stringstr5=“ab”+”c”;charch=“a”;Stringstr11=newString("abc");Stringstr22=newString("abc");Stringstr33=newString("ab");Stringstr44=newString("def");System.out.println(str1);System.out.println(str11);System.out.println(str1==str2);}//输出trueSystem.out.println(str1==str5);//输出trueSystem.out.println(str11==str22)//输出falseSystem.out.println(str1==str11);}//输出false}};栈堆abc110925new

String(“abc”)110925str1str11587934常量池ach………str22354752str2new

String(“abc”)栈:保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用(指针)。也可以用来保存加载方法时的帧。

堆:用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。三个关键存储运行时数据的地方(栈,堆,常量池)一:在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因

在方法中声明的变量可以是基本类型的变量,也可以是引用类型的变量。

(1)当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在JAVA虚拟机栈中

(2)当声明的是引用(变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在 JAVA虚拟机的栈中,该变量所指向的对象是放在堆类存中的。二:在类中声明的变量是成员变量,也叫全局变量,放在堆中的(因为全局变量不会随着某个方法执行结束而销毁)。

同样在类中声明的变量即可是基本类型的变量也可是引用类型的变量

(1)当声明的是基本类型的变量其变量名及其值放在堆内存中的

(2)引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象。引用变

量名和对应的对象仍然存储在相应的堆中。java中的基本数据类型一定存储在栈中的吗?错基本数据类型是放在栈中还是放在堆中,这取决于基本类型在何处声明Java代码

classBirthDate{

privateintday;

privateintmonth;

privateintyear;

publicBirthDate(intd,intm,inty){

day=d;

month=m;

year=y;

}省略get,set方法………

}publicclassTest{

publicstaticvoidmain(Stringargs[]){

intdate=9;

Testtest=newTest();

test.change(date);

BirthDated1=newBirthDate(7,7,1970);

}

publicvoidchange(inti){

i=1234;

}对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:

1.main方法开始执行:intdate=9;

date局部变量,基础类型,引用和值都存在栈中。

2.Testtest=newTest();

test为对象引用,存在栈中,对象(newTest())存堆中。

3.test.change(date);

i为局部变量,引用和值存在栈中。当方法change执行完

成后,i就会从栈中消失。

4.BirthDated1=newBirthDate(7,7,1970);

d1为对象引用,存在栈中,对象(newBirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(newBirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。

5.main方法执行完之后,date变量,test,d1引用将从栈中消失,newTest(),newBirthDate()将等待垃圾回收。Java内存分析JavaCompiler(Java编译器)Java源程序(*.Java)Java字节码文件(*.class)Classloader(类加载器)ExecutionEngine(执行引擎)Nativeinterface(本地方法接口)NativeLibraries(本地方法库)RuntimeDataArea(运行时数据区)JavaVirtualMachine方法区MethodAreaJavaRuntimeAreaJava运行时数据区Java虚拟机栈JavaStackJava本地方法栈NativeMethodStackJava堆Heap程序计数器ProgramCounterRegister每个线程对象独享所有线程对象共享栈(JavaStack):又叫堆栈。JVM为每个新创建的线程都分配一个栈。也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。我们知道,某个线程正在执行的方法称为此线程的当前方法。我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的Java堆栈里新压入一个帧,这个帧自然成为了当前帧。在此方法执行期间,这个帧将用来保存参数、局部变量、中间计算过程和其他数据。从Java的这种分配机制来看,堆栈又可以这样理解:栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。其相关设置参数:-Xss–设置方法栈的最大值本地方法栈(NativeMethodStack):存储本地方方法的调用状态。程序计数器(ProgramCountRegister):又叫程序寄存器。JVM支持多个线程同时运行,当每一个新线程被创建时,它都将得到它自己的PC寄存器(程序计数器)。如果线程正在执行的是一个Java方法(非native),那么PC寄存器的值将总是指向下一条将被执行的指令,如果方法是native的,程序计数器寄存器的值不会被定义。JVM的程序计数器寄存器的宽度足够保证可以持有一个返回地址或者native的指针。堆(Heap):Java堆(JavaHeap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域。在此区域的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存,但是这个对象的引用却是在栈(Stack)中分配。比如,执行Strings=newString(“s”)时,需要从两个地方分配内存:在堆中为String对象分配内存,在栈中为引用(这个堆对象的内存地址,即指针)。线程这里所说的线程指程序执行过程中的一个线程实体。JVM允许一个应用并发执行多个线程。HotspotJVM中的Java线程与原生操作系统线程有直接的映射关系。当线程本地存储、缓冲区分配、同步对象、栈、程序计数器等准备好以后,就会创建一个操作系统原生线程。Java线程结束,原生线程随之被回收。操作系统负责调度所有线程,并把它们分配到任何可用的CPU上。当原生线程初始化完毕,就会调用Java线程的run()方法。run()返回时,被处理未捕获异常,原生线程将确认由于它的结束是否要终止JVM进程(比如这个线程是最后一个非守护线程)。当线程结束时,会释放原生线程和Java线程的所有资源。JVM系统线程如果使用jconsole或者其它调试器,你会看到很多线程在后台运行。这些后台线程与触发publicstaticvoidmain(String[])函数的主线程以及主线程创建的其他线程一起运行。HotspotJVM后台运行的系统线程主要有右面几个:虚拟机线程(VMthread这个线程等待JVM到达安全点操作出现。这些操作必须要在独立的线程里执行,因为当堆修改无法进行时,线程都需要JVM位于安全点。这些操作的类型有:stop-the-world垃圾回收、线程栈dump、线程暂停、线程偏向锁(biasedlocking)解除。周期性任务线程这线程负责定时器事件(也就是中断),用来调度周期性操作的执行。GC线程这些线程支持JVM中不同的垃圾回收活动。编译器线程这些线程在运行时将字节码动态编译成本地平台相关的机器码。信号分发线程这个线程接收发送到JVM的信号并调用适当的JVM方法处理。线程一线程三线程二PC寄存器栈帧栈帧栈帧栈帧栈帧栈帧栈帧线程三Java栈本地方法栈线程一线程三线程二栈帧(StackFrame)栈帧(StackFrame)栈帧(StackFrame)栈帧(StackFrame)栈帧(StackFrame)栈帧(StackFrame)栈帧(StackFrame)局部变量表操作数栈指向运行时常量的引用方法返回地址动态链接栈顶(当前方法)(StackFrame)Java虚拟机栈(JavaVirtualMachineStacks)1.栈内存是线程共有的,其生命周期与线程相同。2.虚拟机描述的是Java方法执行的内存模型:执行一个方法会产生一个栈帧,随后将其保存到栈(后进先出)的顶部,方法执行完毕后会自动将此栈帧进行出栈。顶部的栈帧表示的就是当前的方法。如果请求的栈的深度过大,虚拟机可能会抛出StackOverflowError异常如果虚拟机的实现中允许,虚拟机栈动态扩展,当内存不足以扩展栈的时候,会抛出OutOfMemory异常。局部变量表(LocalVariables):方法的局部变量或形参,其以变量槽(solt)为最小单位,只允许保存32位长度的变量,如果超过32位则会开辟两个连续的solt(64位,long和double)。操作数栈(OperandStack):表达式计算在栈中完成。指向当前方法所属的类的运行时常量池的引用(ReferencetoRuntimeConstantPool):引用其他类的常量或者使用String池中的字符串。方法返回地址(ReturnAddress):方法执行完成后需要返回调用此方法的位置,所以需要在栈中保存方法的返回地址。动态链接(dynamiclinking):每个栈帧都有一个运行时常量池的引用。这个引用指向栈帧当前运行方法所在类的常量池。通过这个引用支持动态链接(dynamiclinking)。C/C++代码一般被编译成对象文件,然后多个对象文件被链接到一起产生可执行文件或者dll。在链接阶段,每个对象文件的符号引用被替换成了最终执行文件的相对偏移内存地址。在Java中,链接阶段是运行时动态完成的。当Java类文件编译时,所有变量和方法的引用都被当做符号引用存储在这个类的常量池中。符号引用是一个逻辑引用,实际上并不指向物理内存地址。JVM可以选择符号引用解析的时机,一种是当类文件加载并校验通过后,这种解析方式被称为饥饿方式。另外一种是符号引用在第一次使用的时候被解析,这种解析方式称为惰性方式。无论如何,JVM必须要在第一次使用符号引用时完成解析并抛出可能发生的解析错误。绑定是将对象域、方法、类的符号引用替换为直接引用的过程。绑定只会发生一次。一旦绑定,符号引用会被完全替换。如果一个类的符号引用还没有被解析,那么就会载入这个类。每个直接引用都被存储为相对于存储结构(与运行时变量或方法的位置相关联的)偏移量。运行时常量池堆数据类型数字型字符串型类引用型域引用型方法引用数据类型对象(实例)数组publicclassdemo{publicstaticvoidmain(String[]args){Stringa="abc";int[]a1={1,2,3};System.out.println(a);System.out.println(a1[0]);}}Class文件中的常量池:在Class文件结构中,最头的4个字节用于存储魔数MagicNumber,用于确定一个文件是否能被JVM接受,再接着4个字节用于存储版本号,前2个字节存储次版本号,后2个存储主版本号,再接着是用于存放常量的常量池,由于常量的数量是不固定的,所以常量池的入口放置一个U2类型的数据(constant_pool_count)存储常量池容量计数值。

常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(SymbolicReferences),字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念,包括了如下三种类型的常量:类和接口的全限定名字段名称和描述符方法名称和描述符详细请看连接:/p/c7f47de2ee80Integer4字节常量Long8字节常量Float4字节常量Double8字节常量String字符串常量指向常量池的另外一个包含真正字节Utf8编码的实体Utf8Utf8编码的字符序列字节流Class一个Class常量,指向常量池的另一个Utf8实体,这个实体包含了符合JVM内部格式的类的全名(动态链接过程需要用到)NameAndType冒号(:)分隔的一组值,这些值都指向常量池中的其它实体。第一个值(“:”之前的)指向一个Utf8字符串实体,它是一个方法名或者字段名。第二个值指向表示类型的Utf8实体。对于字段类型,这个值是类的全名,对于方法类型,这个值是每个参数类型类的类全名的列表。Fieldref,Methodref,InterfaceMethodref点号(.)分隔的一组值,每个值都指向常量池中的其它的实体。第一个值(“.”号之前的)指向类实体,第二个值指向NameAndType实体。这个常量池包含了下面的类型JavaMemoryModelHeapPermGen(MethodArea)ThreadYoungGenerationOld/TenuredGenerationEdenSpace(Survivor0)FromSpace(Survivor1)ToSpaceVMMetaspaceJava8中替换成了VMMetaspaceHeap-sharedamongallthreads

(globle)-StoresallcreatedobjectsandarraysMethodArea-sharedamongallthreads(globle)-Storesclassstructureslikefieldandmethoddata,codeformetholdsandconstructors,etcThread-privatestack(local)-Holdsreferencestoobjectsintheheap-StorelocalvariablesofprimitivetypesHeapSpaceMethodAreaNativeAreaYoungGenerationOldGenerationPermanentGenerationCodeCacheVirtualFr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论