精华内容
下载资源
问答
  • 1. 局部变量表的变量名是来的? 2. 局部变量表并不保存局部变量的值,那这个值是储存哪里的? 字节码指令`iload_2`的意思是拿出局部变量表中位置为2的变量,应该是拿值出来吧,可是这个值局部变量表并没有存啊...
  • this关键字的主要用途是构造方法当中,区分成员变量和参数变量 因为当成员变量与参数变量的名字冲突时,就会采用就近原则,同名变量时就会使用参数变量。 public class demo01 { int id; String name; public...
    区别 成员变量 局部变量
    位置 在class大括号以内 除class大括号,其他大括号以内
    内存存储 是随着类对象存储于内存的堆区 存储于内存的栈区
    初始值 成员变量初始值在没有被构造方法赋值的情况下,默认是对应数据类型的"0"值 Java中规定,局部变量未赋值情况下,不得参与其他运算
    作用域 成员变量作用域是受到当前所在类对象作用范围控制 局部变量作用域范围有且只在当前大括号以内,并且是从定义位置开始往后
    生存期 是随着类对象的创建而出现,随着类对象的销毁而终止。JVM的GC 在所处大括号以内,从定义位置开始到大括号结束
    展开全文
  • 在执行了上面的代码之后出现了这样的 错误,打印出来的东西全部都是乱码,这个很奇怪啊,上面代码怎么看也找不到哪里会有问题啊,既然出现问题了,在表面上也找不到错误在哪,因此,只有通过debug来查找错误了。...


    // normal_bug.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include"iostream"
    #include <deque>
    #pragma warning(disable:4996) 
    
    using namespace std;
    
    deque<char*> getDeque();
    int main()
    {
    	for (auto deque : getDeque())
    	{
    		cout << deque << endl;
    	}
        return 0;
    }
    
    deque<char*> getDeque() {
    
    	char a[5][20] = {
    		"11111",
    		"22222",
    		"33333",
    		"44444",
    		"55555"
    	};
    	deque<char*> myDeque;
    	for (size_t i = 0; i < 5; i++)
    	{
    		char ptemp[20];
    		strcpy(ptemp, a[i]);
    		myDeque.push_back(ptemp);
    	}
    	
    	return myDeque;
    }
    
    






    在执行了上面的代码之后出现了这样的 错误,打印出来的东西全部都是乱码,这个很奇怪啊,上面代码怎么看也找不到哪里会有问题啊,既然出现问题了,在表面上也找不到错误在哪,因此,只有通过debug来查找错误了。






    从上面的debug中好像看到了一些问题了,在deque里面所有的字符串都是 “55555”,而且他们的地址都是一样的,而且还有一个问题,在最后输出的时候都是乱码的,并不是“55555”。然后我能想到的就是可能局部的变量   char ptemp[20];  这句代码有问题,我的猜想是:ptemp 是个for循环里的局部变量,每一次循环ptemp都会经历地址空间的分配和销毁,但是每一次进行地址空间的再分配时都是原来的那个地址,然后我们每一次将ptemp  push_back()到deque中时都是同一个地址,保存的都是同一个字符串,当跳出for循环时ptemp 的作用域已经失效,地址空间被收回,故最后我们看到输出都是乱码的,那么我们就再次修改一下代码。给局部变量自己进行地址空间的分配

    char ptemp[20];


    以下是修改后的代码

    // normal_bug.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include"iostream"
    #include <deque>
    #pragma warning(disable:4996) 
    
    using namespace std;
    
    deque<char*> getDeque();
    int main()
    {
    	for (auto deque : getDeque())
    	{
    		cout << deque << endl;
    	}
        return 0;
    }
    
    deque<char*> getDeque() {
    
    	char a[5][20] = {
    		"11111",
    		"22222",
    		"33333",
    		"44444",
    		"55555"
    	};
    	deque<char*> myDeque;
    	for (size_t i = 0; i < 5; i++)
    	{
    		char* ptemp = (char*)malloc(sizeof(char) * 20);
    		strcpy(ptemp, a[i]);
    		myDeque.push_back(ptemp);
    	}
    	
    	return myDeque;
    }
    
    

    然后再重新运行以下,然后就可以了,最后证实我的猜想是对的






    展开全文
  • 无论通过种方式退出,方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常来确定(go...

    方法返回地址

    存放调用该方法的pc寄存器的值(回到调用该方法前,原本的位置上继续执行)。一个方法的结束,有两种方式:

    • 正常执行完成

    • 出现未处理的异常,非正常退出

    无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定(go to 结构,强制定向),栈帧中一般不会保存这部分信息。

    当一个方法开始执行后,只有两种方式可以退出这个方法:

    执行引擎遇到任意一个方法返回的字节码指令(return),会有返回值传递给上层的方法调用者,简称正常完成出口;

    一个方法在正常调用完成之后,究竟需要使用哪一个返回指令,还需要根据方法返回值的实际数据类型而定。
    在字节码指令中,返回指令包含ireturn(当返回值是boolean,byte,char,short和int类型时使用),lreturn(Long类型),freturn(Float类型),dreturn(Double类型),areturn。另外还有一个return指令声明为void的方法,实例初始化方法,类和接口的初始化方法使用。
    在方法执行过程中遇到异常(Exception),并且这个异常没有在方法内进行处理,也就是只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,简称异常完成出口。

    方法执行过程中,抛出异常时的异常处理,存储在一个异常处理表,方便在发生异常的时候找到处理异常的代码
    在这里插入图片描述

    本质上,方法的退出就是当前栈帧出栈的过程。此时,需要恢复上层方法的局部变量表、操作数栈、将返回值压入调用者栈帧的操作数栈、设置PC寄存器值等,让调用者方法继续执行下去。

    正常完成出口和异常完成出口的区别在于:通过异常完成出口退出的不会给他的上层调用者产生任何的返回值

    一些附加信息

    栈帧中还允许携带与Java虚拟机实现相关的一些附加信息。例如:对程序调试提供支持的信息。

    • 栈的相关面试题
      • 举例栈溢出的情况?(StackOverflowError
        • 通过 -Xss设置栈的大小
      • 调整栈大小,就能保证不出现溢出么?
        • 不能保证不溢出
      • 分配的栈内存越大越好么?
        • 不是,一定时间内降低了OOM概率,但是会挤占其它的线程空间,因为整个空间是有限的。
      • 垃圾回收是否涉及到虚拟机栈?
        • 不会
      • 方法中定义的局部变量是否线程安全?
        • 具体问题具体分析 (应该看,该方法是否有机会被其他的方法或程序所调用,有机会则线程不安全,没有机会则线程安全
    /**
     * 面试题
     * 方法中定义局部变量是否线程安全?具体情况具体分析
     * 何为线程安全?
     *    如果只有一个线程才可以操作此数据,则必是线程安全的
     *    如果有多个线程操作,则此数据是共享数据,如果不考虑共享机制,则为线程不安全
     * @author: 陌溪
     * @create: 2020-07-06-16:08
     */
    public class StringBuilderTest {
    
        // s1的声明方式是线程安全的
        public static void method01() {
            // 线程内部创建的,属于局部变量
            StringBuilder s1 = new StringBuilder();
            s1.append("a");
            s1.append("b");
        }
    
        // 这个也是线程不安全的,因为有返回值,有可能被其它的程序所调用
        public static StringBuilder method04() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("a");
            stringBuilder.append("b");
            return stringBuilder;
        }
    
        // stringBuilder 是线程不安全的,操作的是共享数据
        public static void method02(StringBuilder stringBuilder) {
            stringBuilder.append("a");
            stringBuilder.append("b");
        }
    
    
        /**
         * 同时并发的执行,会出现线程不安全的问题
         */
        public static void method03() {
            StringBuilder stringBuilder = new StringBuilder();
            new Thread(() -> {
                stringBuilder.append("a");
                stringBuilder.append("b");
            }, "t1").start();
    
            method02(stringBuilder);
        }
    
        // StringBuilder是线程安全的,但是String也可能线程不安全的
        public static String method05() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("a");
            stringBuilder.append("b");
            return stringBuilder.toString();
        }
    }
    

    总结一句话就是:如果对象是在内部产生,并在内部消亡,没有返回到外部,那么它就是线程安全的,反之则是线程不安全的。

    运行时数据区,是否存在Error和GC?
    在这里插入图片描述

    展开全文
  • 局部变量存在局部变量保存栈内存区 栈内存区的地址是连续的,由系统控制速度较快 堆内存区的地址时不连续的,它是把系统中空闲的内存连接起来的链表 栈是系统根据变量自动分配大小的 堆中分配内存是通过...

    局部变量存在哪?

    局部变量保存在栈内存区
    栈内存区的地址是连续的,由系统控制速度较快
    堆内存区的地址时不连续的,它是把系统中空闲的内存连接起来的链表

    栈是系统根据变量自动分配大小的
    堆中分配内存是通过malloc函数或者是new来申请分配

    用户使用malloc或者是new申请内存的时候,找到第一个满足大小的空间,即从链表中删除这个节点
    之后就分配给用户使用,没有栈内存使用快,但是很灵活

    new和malloc的区别

    1.首先是属性上的区别,new是编译器支持的,malloc是头文件支持的

    2.参数的区别 malloc中的参数得是自己分配的内存的大小得是手动添加的
    使用new关键字无需手动指定内存块的大小,编译器会自动根据类型进行计算

    3.返回类型的区别 new的操作符执行成功之后,返回指针类型的对象且严格和对象匹配,无需进行类型转换,new是安全性较高的操作符
    malloc执行成功之后返回的类型是void 我们必须通过强制转换来转换成目标类型

    4.自定义类型的区别 关键字new执行的时候回首先执行operator new函数,申请足够的内存,根据调用类型调用构造函数,初始化成员变量,返回自定义类型的指针
    malloc只能动态申请内存,无法强制其做自定义的类型构造和构析工作

    5.对于重载的区别 c++对于new是允许重载的,而malloc是不允许的

    进程和线程是什么,对一个操作用多进程和多线程有什么区别和缺点

    进程和线程是什么

    进程是系统中正在运行的一个程序,程序一旦运行就是进程
    进程可以看做是程序执行的一个实例,进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间。
    一个进程无法访问另一个进程的变量和数据结构,如果想要访问另一个进程的资源,必须使用进程之间的通信(管道,文件等)

    一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间,线程和进程的主要区别就是
    同一进程内的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法访问另一个进程的内存)
    每个线程拥有自己的寄存器和栈,其他线程也可以读写这些栈内存

    线程是进程的一个实体,是进程的一条执行路径。

    进程和线程的区别

    根本区别
    进程是资源分配最小单位,线程是程序执行最小单位。
    计算机在执行程序段过程中,会为程序创建相应的进程
    进行资源分配的时候,是以进程为单位进行相应的分配
    每个进程都有相应的线程,在执行程序的时候,实际上是执行相应的一系列线程

    地址空间:
    进程有自己独立的地址空间,每启动一个进程,系统会为其分配地址空间,建立数据表来维护代码段,堆栈段,数据段
    线程没有自己独立的地址空间,统一进程的线程共享本进程的地址空间

    资源拥有: 进程之间的资源都是独立的,同一进程内的线程共享本进程的资源

    执行过程
    每个独立的进程都有一个程序的入口,顺序执行序列
    线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制

    线程是处理机调度的基本单位,进程不是,由程序执行的过程其实是执行具体的线程,那么处理机处理的 也是程序相应的线程
    所以处理机调度的基本单位是线程

    系统开销
    进程执行开销大,线程执行开销小

    对一个操作用多进程和多线程有什么区别和缺点

    多进程和多线程编程都可以使用并行机制来提升系统的运行效率。二者的区别在于运行时所占的内存分布不同
    多线程公用一套内存的代码块区间;多进程是各用一套独立的内存区间

    多进程优点 稳定性好,假如一个子进程崩溃了不会影响主进程以及其余进程,基于这个特性多用于守护服务器的功能
    多进程缺点 创建进程的代价非常大,操作系统给每个进程分配固定的资源,且操作系统对于进程的个数也是有限制的
    如果进程数量过多,进程调度会出现问题,出现假死状态

    多线程优点 效率高一些,适用于批处理任务等功能
    多线程缺点 任何一个线程崩溃会导致整个进程崩溃,因为他们共享资源

    TCP和UDP是什么,什么时候用TCP,什么时候用UDP,游戏的话用什么

    TCP和UDP是TCP/IP协议中的两个传输层协议,他们使用IP路由功能吧数据包发送到目的地,从而为应用程序以及应用层协议提供网络服务

    TCP
    对于文件传输,远程终端这些应用来说,是不允许数据丢失的,因为TCP提供了超时和重传等可靠机制,因此采用TCP

    UDP
    因为UDP是不可靠传输,所以当包量比较小的时候使用UDP是比较合适的,这样可以避免丢失大量的重要数据
    对于音视频来说,因为UDP是非连接的,所以占用资源比较少,而且对于音视频来说,丢掉一些数据包是可以接收的

    如果网络比较好的话,可以考虑使用UDP,否则TCP就是首选(保证数据的可靠性)
    局域网大多用UDP,但是广域网绝大部分是(可以说全部)Tcp
    上边只是我浅薄的理解,如果有不对的地方,欢迎指正

    进程间的通讯方式有哪些

    1.管道: 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程之间才能使用,亲缘关系通常指父子关系
    2.有名管道: 有名管道也是一种半双工的通信方式,但是允许无亲缘关系的两个进程之间相互通信
    3.信号量 信号量是一个计数器,可以用来控制多个进程对共享资源的访问,常常作为进程间控制同步和互斥的工具
    4.消息队列 消息队列是消息的链表,存放在内核中并由消息队列标识符标识,消息队列客服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限的缺点
    5.信号 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生
    6.共享内存: 共享内存就是映射一段能被其他进程访问的内存,这段共享内存由一个进程创建,但是多个内存都可访问,共享内存最快的是IPC方式,他是针对其他进程运行效率低而专门设计的,和其他通信机制(信号量等)配合使用,来实现进程之间的同步和通信
    7.套接字 套接口是一种进程间通信机制,与其他通信机制不同的地方时,它可用于不同的进程以及之间的进程通信

    线程通信只有管道共享内存

    希望我所写的对大家有些许帮助

    展开全文
  • 每个方法调用的过程,就代表了一个栈帧虚拟机栈中入栈到出栈的过程,当进入一个方法时,这个方法栈中需要分配多大的内存都是完全确定的,方法运行时不会改变局部变量表的大小——《深入理解java虚拟机第二版》 ...
  • class{ private int i; } 如上代码,基本数据类型...java虚拟机是线程私有的,生命周期跟线程是相同的,每个方法调用的时候都会创建一个栈桢用于存储局部变量表,操作数栈,动态链接,方法出口信息等。 2.每个方法...
  • 运行时数据区概述程序计数器(Program Counter Register)是一块较小的内存空间,可以看作是当前线程所...栈帧中存储了局部变量表、操作数栈、动态连接和方法出口等信息。每个方法从调用到运行结束的过程,就对应着...
  • 虚拟机执行时依据这个值来分配栈帧的操作数栈深度max_locals:局部变量表所需存储空间,单位为Slot(參见备注四)。并非全部局部变量占用的Slot之和,当一个局部变量的生命周期结束后。其所占用的Slot将分配给其他依旧...
  • 内存分配: 对于局部变量而言,内存分配的顺序和代码的顺序是一样的,但全局变量...2)对于没有初始化的全局变量,因为不知道是定义还是声明,所以要扫描完所有代码之后才能决定,这个时候编译器会读符号,然后看
  • java粗略理解jvm

    2020-05-16 11:12:38
    和执行顺序,局部变量,作用域,局部变量表相关的东西都在栈内 出了花括号算执行完毕(计数器控制怎么算入栈怎么算出栈) 等号号前边是句柄信息,等号后边是值信息 句柄信息在哪 并不是所有的句柄都在栈内 句柄信息...
  • A:JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈,运行时常量池(六个部分,分别解释如下)虚拟机栈:线程私有的,每个方法执行时会创建一个栈帧,用来存储局部变量表、操作数栈、动态连接、方法...
  • 虚拟机栈:线程私有的,每个方法执行时会创建一个栈帧,用来存储局部变量表、操作数栈、动态连接、方法返回地址等;其中局部变量表用于存放 8 种基本数据类型(boolean、byte、char、short、int、float、long、dou...
  • 虚拟机栈:线程私有的,每个方法执行时会创建一个栈帧,用来存储局部变量表、操作数栈、动态连接、方法返回地址等;其中局部变量表用于存放 8 种基本数据类型(boolean、byte、char、short、int、float、lon...
  • 1、栈帧: 局部变量表(方法局部变量,方法参数)、操作数栈(方法执行中间结果)、方法返回地址、类当前方法的运行时常量池引用; 2、程序计数器:记录线程当前执行到了一条指令,多个线程上下文切换时,能够准确...
  • 元空间: 叫什么? 答: MetaSpace区 位置在哪?答:本地内存-nativeMemorySpace ...方法信息:(方法名称 返回类型 方法参数 方法修饰符 方法字节码 操作数栈 方法帧栈局部变量表大小 异常表) 干什么?...
  • jvm加载

    2019-10-24 09:58:04
    有栈帧每一个方法代表一个栈帧,栈帧中有局部变量表(变量,存放对象堆中的地址)、 操作数栈(对变量的操作加减乘除等)、动态链接、方法出口(return) ) 堆中的对象是怎么通过回收的minor gc和full gc 以及...
  • 2.修饰局部变量 const int a = 10; int const b = 20; 这两种写法是等价的,都是表示变量的值不能被改变,需要注意的是,用const修饰变量时,一定要给变量初始化,否则之后就不能再进行赋值了,而且编译器也不...
  • 一、Java的运行时区域Java中,...虚拟机栈:这就是我们平时所说的栈了,一般用来储存局部变量表、操作数表、动态链接等。本地方法栈:这是另一个栈,用来提供虚拟机中用到的本地服务,像线程中的start方法,J...
  • 函数包括函数名,参数,函数体。...不管种类型,我们需要提取其名字f,保存在局部变量表里,这个倒是不难。然后是对函数的每个部分逐一解析。函数参数是名字变量列表,这个相当于初始化名字列表,...
  • JVM(二)垃圾回收

    2019-02-06 21:00:00
    要弄懂JVM的垃圾回收,首先要知道我们要回收什么,在哪回收,什么时候回收。 一、JVM内存模型 java虚拟机把内存模型分为了这么几部分 ...用于存放局部变量表、操作数栈、动态链接、返回地址等。...
  • 详解JVM和GC垃圾回收

    2020-06-14 21:45:05
    Java虚拟机栈:存局部变量表,操作数栈,动态链接,方法出口等 本地方法栈:与虚拟机栈一样,只不过调用native服务 Java堆:存放数组,和对象实例,该区域线程共享 方法区:也叫永久代,存类信息,常量,静态变量。...
  • 运行时数据区域

    2020-06-11 19:56:25
    虚拟机栈:存储局部变量表、操作数栈、动态链接、方法出口等信息 本地方法栈:本地方法栈是为虚拟机调用 Native 方法服务的 堆 : 主要储存对象。 方法区:已被虚拟机加载的类信息、常量、静态变量、即时编译后的
  • Java内存区域

    2019-03-09 14:21:00
    JVM内存分为几部分,这些部分分别都存储哪些数据?...Java虚拟机栈 Java虚拟栈描述的是Java方法执行的内存模型:每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。...
  •  2 Java虚拟机栈:用于存放方法的入口,局部变量表,动态链接,操作数栈。  3 本地虚拟机栈:和Java虚拟机类似,但是他只能为本地方法服务。  4 Java堆:用于存放对象实例,也是垃圾收集器的管理的地方。  5 ...
  • 例如,iload指令用于从局部变量表中加载int型的数据到操作数栈中,而fload指令加载的则是float类型数据到操作数栈中。这两条指令的操作虚拟机内部可能会是由同一段代码来实现的,但是Class文件中它们必须拥有...
  • jvm 的一些基本信息

    2019-05-09 16:10:36
    栈:描述的是 Java 方法执行的内存模型:每个方法执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从开始到最后执行完的过程,就对应者一个栈帧入栈到出栈的过程. ...
  • Jvm :栈 ...Jvm栈和堆的关系(栈中对象类型的局部变量会指向堆中相应对象的内存地址) 方法区(元空间)用于存放常量,静态变量以及类信息,其中静态变量的对象类型存放堆中对象的内存地址 本地方法
  • JVM基础

    2018-07-06 12:14:28
    Java虚拟机深入理解JVM读书笔记,先简单整理下,...调用方法时会创建栈帧,用于保存局部变量表、操作数栈、动态链接、方法出口等信息。本地方法栈:跟Java虚拟机栈相似,只不过这里存的是native方法的信息。Java堆...

空空如也

空空如也

1 2 3 4 5
收藏数 88
精华内容 35
关键字:

局部变量表在哪