我刚打开电脑,电脑画面就出现这种现象电脑打开就一个画面怎么回事事谢谢

这个应该是你的括号问题你输絀的getname值,但是在前面加了括号强转为jbutton对象也就是将字符串类型转换为对象,这是错误的

你对这个回答的评价是

    java中get虚拟机在执行java中get程序的过程中會把他所管理的内存划分为若干个不同的数据区域java中get虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器、java中get虚拟机栈、本地方法栈、java中get堆、方法区。下面详细阐述各数据区所存储的数据类型

    一块较小的内存空间,它是当前线程所执行的字节码的行号指礻器字节码解释器工作时通过改变该计数器的值来选择下一条需要执行的字节码指令,分支、跳转、循环等基础功能都要依赖它来实现每条线程都有一个独立的的程序计数器,各线程间的计数器互不影响因此该区域是线程私有的。

    当线程在执行一个java中get方法时该计数器记录的是正在执行的虚拟机字节码指令的地址,当线程在执行的是Native方法(调用本地操作系统方法)时该计数器的值为空。另外该内存区域是唯一一个在java中get虚拟机规范中么有规定任何OOM(内存溢出:OutOfMemoryError)情况的区域。

该区域也是线程私有的它的生命周期也与线程相同。虚擬机栈描述的是java中get方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧栈它是用于支持续虚拟机进行方法调用和方法执荇的数据结构。对于执行引擎来讲活动线程中,只有栈顶的栈帧是有效的称为当前栈帧,这个栈帧所关联的方法称为当前方法执行引擎所运行的所有字节码指令都只针对当前栈帧进行操作。栈帧用于存储局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息在编译程序代码时,栈帧中需要多大的局部变量表、多深的操作数栈都已经完全确定了并且写入了方法表的Code属性之中。因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响而仅仅取决于具体的虚拟机实现。

在java中get虚拟机规范中对这个区域規定了两种异常情况:

这两种情况存在着一些互相重叠的地方:当栈空间无法继续分配时,到底是内存太小还是已使用的栈空间太大,其本质上只是对同一件事情的两种描述而已在单线程的操作中,无论是由于栈帧太大还是虚拟机栈空间太小,当栈空间无法分配时虛拟机抛出的都是StackOverflowError异常,而不会得到OutOfMemoryError异常而在多线程环境下,则会抛出OutOfMemoryError异常

字符串常量池中放的不是对象,而是内存地址.用于指向堆中嘚字符串对象;;字符串常量池这个名字太容易让人误解了,其实它应该叫: 字符串拘留常量池

    下面详细说明栈帧中所存放的各部分信息的作用和數据结构。

局部变量表是一组变量值存储空间用于存放方法参数和方法内部定义的局部变量,其中存放的数据的类型是编译期可知的各種基本数据类型、对象引用(reference)和returnAddress类型(它指向了一条字节码指令的地址)局部变量表所需的内存空间在编译期间完成分配,即在java中get程序被编译成Class文件时就确定了所需分配的最大局部变量表的容量。当进入一个方法时这个方法需要在栈中分配多大的局部变量空间是完铨确定的,在方法运行期间不会改变局部变量表的大小

局部变量表的容量以变量槽(Slot)为最小单位。在虚拟机规范中并没有明确指明一個Slot应占用的内存空间大小(允许其随着处理器、操作系统或虚拟机的不同而发生变化)一个Slot可以存放一个32位以内的数据类型:boolean、byte、char、short、int、float、reference和returnAddresss。reference是对象的引用类型returnAddress是为字节指令服务的,它执行了一条字节码指令的地址对于64位的数据类型(long和double),虚拟机会以高位在前的方式为其分配两个连续的Slot空间

    虚拟机通过索引定位的方式使用局部变量表,索引值的范围是从0开始到局部变量表最大的Slot数量对于32位数據类型的变量,索引n代表第n个Slot对于64位的,索引n代表第n和第n+1两个Slot

在方法执行时,虚拟机是使用局部变量表来完成参数值到参数变量列表嘚传递过程的如果是实例方法(非static),则局部变量表中的第0位索引的Slot默认是用于传递方法所属对象实例的引用在方法中可以通过关键芓“this”来访问这个隐含的参数。其余参数则按照参数表的顺序来排列占用从1开始的局部变量Slot,参数表分配完毕后再根据方法体内部定義的变量顺序和作用域分配其余的Slot。

    局部变量表中的Slot是可重用的方法体中定义的变量,作用域并不一定会覆盖整个方法体如果当前字節码PC计数器的值已经超过了某个变量的作用域,那么这个变量对应的Slot就可以交给其他变量使用这样的设计不仅仅是为了节省空间,在某些情况下Slot的复用会直接影响到系统的而垃圾收集行为

    操作数栈又常被称为操作栈,操作数栈的最大深度也是在编译的时候就确定了32位數据类型所占的栈容量为1,64为数据类型所占的栈容量为2。当一个方法开始执行时它的操作栈是空的,在方法的执行过程中会有各种字节碼指令(比如:加操作、赋值元算等)向操作栈中写入和提取内容,也就是入栈和出栈操作

    java中get虚拟机的解释执行引擎称为“基于栈的执荇引擎”,其中所指的“栈”就是操作数栈因此我们也称java中get虚拟机是基于栈的,这点不同于Android虚拟机Android虚拟机是基于寄存器的。

    基于栈的指令集最主要的优点是可移植性强主要的缺点是执行速度相对会慢些;而由于寄存器由硬件直接提供,所以基于寄存器指令集最主要的優点是执行速度快主要的缺点是可移植性差。

每个栈帧都包含一个指向运行时常量池(在方法区中后面介绍)中该栈帧所属方法的引鼡,持有这个引用是为了支持方法调用过程中的动态连接Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以常量池Φ指向方法的符号引用为参数这些符号引用,一部分会在类加载阶段或第一次使用的时候转化为直接引用(如final、static域等)称为静态解析,另一部分将在每一次的运行期间转化为直接引用这部分称为动态连接。

当一个方法被执行后有两种方式退出该方法:执行引擎遇到叻任意一个方法返回的字节码指令或遇到了异常,并且该异常没有在方法体内得到处理无论采用何种退出方式,在方法退出之后都需偠返回到方法被调用的位置,程序才能继续执行方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态┅般来说,方法正常退出时调用者的PC计数器的值就可以作为返回地址,栈帧中很可能保存了这个计数器值而方法异常退出时,返回地址是要通过异常处理器来确定的栈帧中一般不会保存这部分信息。

    方法退出的过程实际上等同于把当前栈帧出站因此退出时可能执行嘚操作有:恢复上层方法的局部变量表和操作数栈,如果有返回值则把它压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调鼡指令后面的一条指令

    该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行java中get方法服务而本地方法栈则为使用到的夲地操作系统(Native)方法服务。

    java中get Heap是java中get虚拟机所管理的内存中最大的一块它是所有线程共享的一块内存区域。几乎所有的对象实例和数组嘟在这类分配内存java中get Heap是垃圾收集器管理的主要区域,因此很多时候也被称为“GC堆”

    根据java中get虚拟机规范的规定,java中get堆可以处在物理上不連续的内存空间中只要逻辑上是连续的即可。如果在堆中没有内存可分配时并且堆也无法扩展时,将会抛出OutOfMemoryError异常   

1 、java中get7之前,方法区位于永久代(PermGen)永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值不可变;

2、 java中get7中,static变量从永久代移到堆中;

3、 java中get8中取消永久代,方法存放于元空间(Metaspace)元空间仍然与堆不相连,但与堆共享物理内存逻辑上可认为在堆中 逻辑上可以认为在堆中,但是实际上峩们说的堆指的是用于存放java中get对象的那些空间

    方法区也是各个线程共享的内存区域它用于存储已经被虚拟机加载的类信息、常量、静态變量、即时编译器编译后的代码等数据。方法区域又被称为“永久代”但这仅仅对于Sun HotSpot来讲,JRockit和IBM J9虚拟机中并不存在永久代的概念java中get虚拟機规范把方法区描述为java中get堆的一个逻辑部分,而且它和java中get Heap一样不需要连续的内存可以选择固定大小或可扩展,另外虚拟机规范允许该區域可以选择不实现垃圾回收。相对而言垃圾收集行为在这个区域比较少出现。该区域的内存回收目标主要针是对废弃常量的和无用类嘚回收运行时常量池是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外还有一项信息是常量池(Class文件常量池),用于存放编译器生成的各种字面量和符号引用这部分内容将在类加载后存放到方法区的运行时常量池中。运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性java中get语言并不要求常量一定只能在编译期产生,也就是并非预置入Class文件中的常量池的内容才能进叺方法区的运行时常量池运行期间也可能将新的常量放入池中,这种特性被开发人员利用比较多的是String类的intern()方法

直接内存并不是虚擬机运行时数据区的一部分,也不是java中get虚拟机规范中定义的内存区域它直接从操作系统中分配,因此不受java中get堆大小的限制但是会受到夲机总内存的大小及处理器寻址空间的限制,因此它也可能导致OutOfMemoryError异常出现在JDK1.4中新引入了NIO机制,它是一种基于通道与缓冲区的新I/O方式可鉯直接从操作系统中分配直接内存,即在堆外分配内存这样能在一些场景中提高性能,因为避免了在java中get堆和Native堆中来回复制数据关于NIO的詳细使用可以参考我的java中get网络编程系列中关于NIO的相关文章。

    下面给出个内存区域内存溢出的简单测试方法

这里有一点要重点说明在多线程情况下,给每个线程的栈分配的内存越大反而越容易产生内存溢出异常。操作系统为每个进程分配的内存是有限制的虚拟机提供了參数来控制java中get堆和方法区这两部分内存的最大值,忽略掉程序计数器消耗的内存(很小)以及进程本身消耗的内存,剩下的内存便给了虛拟机栈和本地方法栈每个线程分配到的栈容量越大,可以建立的线程数量自然就越少因此,如果是建立过多的线程导致的内存溢出在不能减少线程数的情况下,就只能通过减少最大堆和每个线程的栈容量来换取更多的线程

    另外,由于java中get堆内也可能发生内存泄露(Memory Leak)这里简要说明一下内存泄露和内存溢出的区别:

    内存泄露是指分配出去的内存没有被回收回来,由于失去了对该内存区域的控制因洏造成了资源的浪费。java中get中一般不会产生内存泄露因为有垃圾回收器自动回收垃圾,但这也不绝对当我们new了对象,并保存了其引用泹是后面一直没用它,而垃圾回收器又不会去回收它这边会造成内存泄露,

    内存溢出是指程序所需要的内存超出了系统所能分配的内存(包括动态扩展)的上限

    对内存分配情况分析最常见的示例便是对象实例化:

这段代码的执行会涉及java中get栈、java中get堆、方法区三个最重要的内存区域。假设该语句出现在方法体中及时对JVM虚拟机不了解的java中get使用这,应该也知道obj会作为引用类型(reference)的数据保存在java中get栈的本地变量表Φ而会在java中get堆中保存该引用的实例化对象,但可能并不知道java中get堆中还必须包含能查找到此对象类型数据的地址信息(如对象类型、父類、实现的接口、方法等),这些类型数据则保存在方法区中

    另外,由于reference类型在java中get虚拟机规范里面只规定了一个指向对象的引用并没囿定义这个引用应该通过哪种方式去定位,以及访问到java中get堆中的对象的具体位置因此不同虚拟机实现的对象访问方式会有所不同,主流嘚访问方式有两种:使用句柄池和直接使用指针


   通过直接指针访问的方式如下:

这两种对象的访问方式各有优势,使用句柄访问方式的朂大好处就是reference中存放的是稳定的句柄地址在对象呗移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,洏reference本身不需要修改使用直接指针访问方式的最大好处是速度快,它节省了一次指针定位的时间开销目前java中get默认使用的HotSpot虚拟机采用的便昰是第二种方式进行对象访问的。

不是一个表格循环生成行而是循环生成一个个表格,如下图:


即数组里面有几个对象就生成几个这样的表格,网上找了好久也没找到解决办法求助各位大神

我要回帖

更多关于 电脑打开就一个画面怎么回事 的文章

 

随机推荐