精华内容
下载资源
问答
  • 为了更加深入的理解方法的覆盖和覆写原理需要了解java方法的调用原理首先解释一下方法调用方法调用不等同于方法执行,方法调用阶段的唯一任务就是确定被调用方法的版本(即确定具体调用那一个方法),不涉及方法...

    为了更加深入的理解方法的覆盖和覆写原理需要了解java方法的调用原理

    首先解释一下方法调用:
    方法调用不等同于方法执行,方法调用阶段的唯一任务就是确定被调用方法的版本(即确定具体调用那一个方法),不涉及方法内部具体运行。

    java虚拟机中提供了5条方法调用的字节码指令:

    invokestatic:调用静态方法
    invokespecial:调用实例构造器<init>方法、私有方法、父类方法
    invokevirtual:调用所有虚方法。
    invokeinterface:调用接口方法,在运行时再确定一个实现该接口的对象
    invokedynamic:运行时动态解析出调用的方法,然后去执行该方法。

    方法调编译成Class字节码后的状态:
    Class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在Class文件里存储的都只是符号引用,而不是具体的方法执行入口地址(即直接引用)。

    所以对于java的方法调用过程就变的复杂起来,需要在类加载期间,甚至是运行期间才能确定目标方法的直接调用。

    关于具体的类加载机制可以参考JVM类加载机制

    1、解析阶段

    Class文件里所有的方法调用都是一个常量池中的符号引用,在类的解析阶段,会将其中一部分符号引用转化为直接引用。转化的这部分方法调用必须是:在程序运行之前就有一个可以确定的调用版本,并且这个调用版本在程序运行期间是不可改变的。

    即:编译期可知,运行期不变的方法调用

    这种类型的方法主要有:静态方法、私有方法。

    只要能被invokestatic和invokespecial指令调用的方法都可以在解析阶段中确定唯一调用版本。符合这个条件主要有:静态方法、私有方法、实例构造器方法、父类方法。他们在类加载的时候就会把符号引用解析为该方法的直接引用。

    2、分派

    就是如何确定执行哪个方法,这里详细解释了重载和重写。

    静态分派

    首先看一个重载的例子

    public class Main2 {
        class A{
        }
        class B extends A{
        }
        public static void f(A a) {
            System.out.println("A");
        }
        public static void f(B b) {
            System.out.println("B");
        }
        public static void main(String[] args) {
            A a = new Main2().new B();
            f(a);
        }
    }

    输出:A

    这里将A称为静态类型或者外观类型,B称为实际类型

    编译器在运行前只知道一个对象的静态类型,并不知道对象的实际类型。

    f方法经过了重载,有两个不同的参数,虚拟机方法调用时,他会直接使用静态类型进行匹配。也就是说:重载时是通过参数的静态类型而不是实际类型作为判定依据。并且静态类型是在编译期可知的,因此在编译阶段,javac编译器就可以根据参数类型确定具体使用哪个重载版本。

    • 所有依赖静态类型来定位方法执行版本的分派动作称为静态分派
    • 静态分派的典型应用就是方法重载
    • 静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的

    动态分派

    这个分派体现了重写

    主要和invokevirtual方法调用字节码有关,运行过程如下:

    1. 找到操作数栈顶的第一个元素所指向的对象的实际类型,记为C;
    2. 在C中寻找与常量中的描述符合简单名都一致的方法,进行权限校验,如通过则返回这个方法的直接引用,查找结束;如果不通过,返回异常。
    3. 否则,按照继承关系从下往上依次对C的各个父类进行第2步搜索和验证。
    4. 如果始终没有找到合适的方法,则抛出异常。

    虚拟机动态分派的实现

    最常用的手段就是在方法区中建立一个虚方法表,如果一个方法在子类中没有被重写,那么子类的虚方法表里的地址入口就和父类对应方法地址入口一致。

    这里写图片描述

    即:每个对象都建立一个如上图的方法虚方法表,表中列出每个对象的所有方法,包括继承的方法,如果重写了对应的方法,则对应的地址就是重写方法的地址,如果没有重写就是原来的方法地址。

    展开全文
  • 深入理解java方法调用时的参数传递

    千次阅读 2017-11-09 18:08:20
    深入理解java方法调用与参数传递,解决以下问题:Java方法调用是如何传递参数的?被调用方法对调用方法内的变量有什么影响?java能使用返回值void的中间方法对变量进行加工吗?为什么静态成员变量的改变影响是全局的...
    深入理解java方法调用与参数传递,解决以下问题:
    1. Java方法调用是如何传递参数的?
    2. 被调用方法对调用方法内的变量有什么影响?
    3. java能使用返回值void的中间方法对变量进行加工吗?
    4. 为什么静态成员变量的改变影响是全局的?
    5. 同一个方法同时被多个线程调用线程安全吗?
    1,每个线程都有一个方法链,即虚拟机栈。虚拟机栈是线程私有的,是方法执行的内存模型,每个栈帧都对应一个执行方法。开始执行,栈帧入栈,执行完毕,栈帧出栈。

    2,局部变量表slot中的值:
    基本类型为字面值,String等引用reference类型为指向堆内句柄的指针或直接指向堆内对象的指针,总之是地址值。(由于reference类型在Java虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位、访问堆中的对象的具体位置,所以对象访问方式也是取决于虚拟机实现而定的。目前主流的访问方式有使用句柄和直接指针两种)
    3,方法中变量的使用基于局部变量表的slot索引值:
    每个方法执行都对应一个栈帧,都有独立的局部变量表,方法执行过程中方法内部通过变量表的slot的索引值来定位和使用变量。所以一个方法调用另一个方法时,不可能将“某个栈的某个栈帧的某个索引值”这种定位描述传递过去,所以方法调用时的参数传递采用值传递——基本类型的字面值、reference的地址值。
    4,方法调用通过操作数栈实现参数传递:
    概念模型下,栈帧上下独立,调用方法对应栈帧中局部变量表和操作数栈都均不受影响;虚拟机优化下,下面栈帧的操作数栈可以与上面栈帧的局部变量表重叠,无需额外的参数复制,调用方法对应栈帧中操作数栈内的值改变,局部变量表不受影响。

    5,被调用方法对调用方法的影响:
    首先,由上可知,每个栈帧的局部变量表都是独立的,不受方法调用影响。
    值操作不会影响到调用方法变量,无论是基本类型的字面值还是引用类型的地址值;
    a=10; //int a
    a=“aaa”; //String a
    a=new User(); //User a
    实例操作改变了引用类型地址值指向的堆内实例信息,堆是共享的,所以调用方法内所看到的实例信息也是被改变的;
         a.setName("aaa"); //User a
    6,既然我们已经说过,每个栈帧的局部变量表都是独立的,参数传递又是值传递,为什么同一实例的方法执行会影响到成员变量,甚至是线程安全?reference类型可能是改变了实例信息,那么基本类型呢?
    由于,存储在局部变量表0位Slot中的是指向自身实例的reference类型“this”。对成员变量的操作,即是对this实例信息的操作。同时单例多线程下,会造成线程安全。线程安全解决方式:
    1. 原子操作(基本类型的读取和赋值):volatile关键字;
    2. 非原子操作:synchronized,Lock
    3. 非原子操作+指令重排序结果受影响:synchronized、 lock+volatile
    4. ThreadLocal<T>;
    7,那么你说实例成员变量是因为0位Slot的引用类型“this”,那么静态成员变量呢?他为什么会在多例情况下,受到方法执行的影响,导致多例多线程的线程安全呢?
    由于在类加载过程中的准备阶段,静态变量的内存被分配到方法区,赋初值(另外,初始化阶段,通过<Clinit>类构造器被初始化,且只执行一次)。而方法区和堆一样是线程共享的内存区域,即对所有线程的所有类型的所有实例的所有方法都是共享的,,,,,就是说谁都能使用它并更改它,且对整个虚拟机产生影响。
    • 静态方法:静态方法中是没有this的引用,所以静态方法中不能直接使用实例变量只能使用静态变量(类变量),直接操作方法区中共享的变量内存;
    • 实例方法:多例情况下,每个this指向一个实例,可以理解为通过操作每个this,间接操作着它们共享的静态变量(实际上,仍然是直接操作方法区中共享的变量内存);
    注意:
    • 静态变量在类加载中被立即解析成指向方法区内存的直接引用(指针),所以执行过程是直接操作方法区共享的变量内存。
    • 实例变量被 立即解析 惰性解析 为相对偏移量,即相对对象头(实例所在内存地址的起始位置)的偏移值,以此来定位不同实例中的变量。
    简单理解为:
    • 方法调用的参数传递是值传递:基本类型字面值、引用类型地址值;
    • 方法执行对应栈帧的局部变量表是独立的,不受方法调用影响;
    • 值操作不会影响调用方法,但实例操作可以改变堆内实例信息,堆内存是共享的。
    展开全文
  • java方法调用之重载、重写的调用原理(一) java方法调用之单分派与多分派(二) 本文大部分内容来自于IBM的博文多态在 Java 和 C++ 编程语言中的实现比较 。这里写一遍主要是加深自己的理解,方便以后查看,加入

    上两篇篇博文讨论了java的重载(overload)与重写(override)、静态分派与动态分派,这篇博文讨论下动态分派的实现方法,即多态override的实现原理。
    java方法调用之重载、重写的调用原理(一)
    java方法调用之单分派与多分派(二)

    本文大部分内容来自于IBM的博文多态在 Java 和 C++ 编程语言中的实现比较 。这里写一遍主要是加深自己的理解,方便以后查看,加入了一些自己的见解及行文组织,不是出于商业目的,如若需要下线,请告知。

    结论

    基于基类的调用和基于接口的调用,从性能上来讲,基于基类的调用性能更高 。因为invokevirtual是基于偏移量的方式来查找方法的,而invokeinterface是基于搜索的。

    概述

    多态是面向对象程序设计的重要特性。多态允许基类的引用指向派生类的对象,而在具体访问时实现方法的动态绑定。
    java对方法动态绑定的实现方法主要基于方法表,但是这里分两种调用方式invokevirtual和invokeinterface,即类引用调用和接口引用调用。类引用调用只需要修改方法表的指针就可以实现动态绑定(具有相同签名的方法,在父类、子类的方法表中具有相同的索引号),而接口引用调用需要扫描整个方法表才能实现动态绑定(因为,一个类可以实现多个接口,另外一个类可能只实现一个接口,无法具有相同的索引号。这句如果没有看懂,继续往下看,会有例子。写到这里,感觉自己看书时,有的时候也会不理解,看不懂,思考一段时间,还是不明白,做个标记,继续阅读吧,然后回头再看,可能就豁然开朗。)。
    类引用调用的大致过程为:java编译器将java源代码编译成class文件,在编译过程中,会根据静态类型将调用的符号引用写到class文件中。在执行时,JVM根据class文件找到调用方法的符号引用,然后在静态类型的方法表中找到偏移量,然后根据this指针确定对象的实际类型,使用实际类型的方法表,偏移量跟静态类型中方法表的偏移量一样,如果在实际类型的方法表中找到该方法,则直接调用,否则,按照继承关系从下往上搜索。
    下面对上面的描述做具体的分析讨论。

    JVM的运行时结构

    这里写图片描述
    从上图可以看出,当程序运行时,需要某个类时,类载入子系统会将相应的class文件载入到JVM中,并在内部建立该类的类型信息,这个类型信息其实就是class文件在JVM中存储的一种数据结构,他包含着java类定义的所有信息,包括方法代码,类变量、成员变量、以及本博文要重点讨论的方法表。这个类型信息就存储在方法区。
    注意,这个方法区中的类型信息跟在堆中存放的class对象是不同的。在方法区中,这个class的类型信息只有唯一的实例(所以是各个线程共享的内存区域),而在堆中可以有多个该class对象。可以通过堆中的class对象访问到方法区中类型信息。就像在java反射机制那样,通过class对象可以访问到该类的所有信息一样。
    方法表是实现动态调用的核心。方法表存放在方法区中的类型信息中。方法表中存放有该类定义的所有方法及指向方法代码的指针。这些方法中包括从父类继承的所有方法以及自身重写(override)的方法。

    类引用调用invokevirtual

    代码如下:

    package org.fan.learn.methodTable;
    
    /**
     * Created by fan on 2016/3/30.
     */
    public class ClassReference {
        static class Person {
            @Override
            public String toString(){
                return "I'm a person.";
            }
            public void eat(){
                System.out.println("Person eat");
            }
            public void speak(){
                System.out.println("Person speak");
            }
    
        }
    
        static class Boy extends Person{
            @Override
            public String toString(){
                return "I'm a boy";
            }
            @Override
            public void speak(){
                System.out.println("Boy speak");
            }
            public void fight(){
                System.out.println("Boy fight");
            }
        }
    
        static class Girl extends Person{
            @Override
            public String toString(){
                return "I'm a girl";
            }
            @Override
            public void speak(){
                System.out.println("Girl speak");
            }
            public void sing(){
                System.out.println("Girl sing");
            }
        }
    
        public static void main(String[] args) {
            Person boy = new Boy();
            Person girl = new Girl();
            System.out.println(boy);
            boy.eat();
            boy.speak();
            //boy.fight();
            System.out.println(girl);
            girl.eat();
            girl.speak();
            //girl.sing();
        }
    }
    

    注意,boy.fight();girl.sing(); 这两个是有问题的,在IDEA中会提示“Cannot resolve method ‘fight()’”。因为,方法的调用是有静态类型检查的,而boy和girl的静态类型都是Person类型的,在Person中没有fight方法和sing方法。因此,会报错。
    执行结果如下:
    这里写图片描述
    从上图可以看到,boy.eat()girl.eat() 调用产生的输出都是”Person eat”,因为Boy和Girl中没有override 父类的eat方法。
    字节码指令:

    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=3, Args_size=1
       0:   new     #2; //class ClassReference$Boy
       3:   dup
       4:   invokespecial   #3; //Method ClassReference$Boy."<init>":()V
       7:   astore_1
       8:   new     #4; //class ClassReference$Girl
       11:  dup
       12:  invokespecial   #5; //Method ClassReference$Girl."<init>":()V
       15:  astore_2
       16:  getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
       19:  aload_1
       20:  invokevirtual   #7; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       23:  aload_1
       24:  invokevirtual   #8; //Method ClassReference$Person.eat:()V
       27:  aload_1
       28:  invokevirtual   #9; //Method ClassReference$Person.speak:()V
       31:  getstatic       #6; //Field java/lang/System.out:Ljava/io/PrintStream;
       34:  aload_2
       35:  invokevirtual   #7; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       38:  aload_2
       39:  invokevirtual   #8; //Method ClassReference$Person.eat:()V
       42:  aload_2
       43:  invokevirtual   #9; //Method ClassReference$Person.speak:()V
       46:  return

    其中所有的invokevirtual调用的都是Person类中的方法。

    下面看看java对象的内存模型:
    这里写图片描述
    从上图可以清楚地看到调用方法的指针指向。而且可以看出相同签名的方法在方法表中的偏移量是一样的。这个偏移量只是说Boy方法表中的继承自Object类的方法、继承自Person类的方法的偏移量与Person类中的相同方法的偏移量是一样的,与Girl是没有任何关系的。

    下面再看看调用过程,以girl.speak() 方法的调用为例。在我的字节码中,这条指令对应43: invokevirtual #9; //Method ClassReference$Person.speak:()V ,为了便于使用IBM的图,这里采用跟IBM一致的符号引用:invokevirtual #12; 。调用过程图如下所示:
    这里写图片描述
    (1)在常量池中找到方法调用的符号引用
    (2)查看Person的方法表,得到speak方法在该方法表的偏移量(假设为15),这样就得到该方法的直接引用。
    (3)根据this指针确定方法接收者(girl)的实际类型
    (4)根据对象的实际类型得到该实际类型对应的方法表,根据偏移量15查看有无重写(override)该方法,如果重写,则可以直接调用;如果没有重写,则需要拿到按照继承关系从下往上的基类(这里是Person类)的方法表,同样按照这个偏移量15查看有无该方法。

    接口引用调用invokeinterface

    代码如下:

    package org.fan.learn.methodTable;
    
    /**
     * Created by fan on 2016/3/29.
     */
    public class InterfaceReference {
        interface IDance {
            void dance();
        }
    
        static class Person {
            @Override
            public String toString() {
                return "I'm a person";
            }
            public void speak() {
                System.out.println("Person speak");
            }
            public void eat() {
                System.out.println("Person eat");
            }
        }
    
        static class Dancer extends Person implements IDance {
            @Override
            public String toString() {
                return "I'm a Dancer";
            }
            @Override
            public void speak() {
                System.out.println("Dancer speak");
            }
            public void dance() {
                System.out.println("Dancer dance");
            }
        }
    
        static class Snake implements IDance {
            @Override
            public String toString() {
                return "I'm a Snake";
            }
            public void dance() {
                System.out.println("Snake dance");
            }
        }
    
        public static void main(String[] args) {
            IDance dancer = new Dancer();
            System.out.println(dancer);
            dancer.dance();
            //dancer.speak();
            //dancer.eat();
            IDance snake = new Snake();
            System.out.println(snake);
            snake.dance();
        }
    }
    

    上面的代码中dancer.speak(); dancer.eat(); 这两句同样不能调用。
    执行结果如下所示:
    这里写图片描述
    其字节码指令如下所示:

    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=3, Args_size=1
       0:   new     #2; //class InterfaceReference$Dancer
       3:   dup
       4:   invokespecial   #3; //Method InterfaceReference$Dancer."<init>":()V
       7:   astore_1
       8:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
       11:  aload_1
       12:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       15:  aload_1
       16:  invokeinterface #6,  1; //InterfaceMethod InterfaceReference$IDance.dance:()V
       21:  new     #7; //class InterfaceReference$Snake
       24:  dup
       25:  invokespecial   #8; //Method InterfaceReference$Snake."<init>":()V
       28:  astore_2
       29:  getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
       32:  aload_2
       33:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       36:  aload_2
       37:  invokeinterface #6,  1; //InterfaceMethod InterfaceReference$IDance.dance:()V
       42:  return

    从上面的字节码指令可以看到,dancer.dance();snake.dance(); 的字节码指令都是invokeinterface #6, 1; //InterfaceMethod InterfaceReference$IDance.dance:()V
    为什么invokeinterface指令会有两个参数呢?

    对象的内存模型如下所示:
    这里写图片描述
    从上图可以看到IDance接口中的方法dance()在Dancer类的方法表中的偏移量跟在Snake类的方法表中的偏移量是不一样的,因此无法仅根据偏移量来进行方法的调用。(这句话在理解时,要注意,只是为了强调invokeinterface在查找方法时不再是基于偏移量来实现的,而是基于搜索的方式。)应该这么说,dance方法在IDance方法表(如果有的话)中的偏移量与在Dancer方法表中的偏移量是不一样的。
    因此,要在Dancer的方法表中找到dance方法,必须搜索Dancer的整个方法表。

    下面写一个,如果Dancer中没有重写(override)toString方法,会发生什么?
    代码如下:

    package org.fan.learn.methodTable;
    
    /**
     * Created by fan on 2016/3/29.
     */
    public class InterfaceReference {
        interface IDance {
            void dance();
        }
    
        static class Person {
            @Override
            public String toString() {
                return "I'm a person";
            }
            public void speak() {
                System.out.println("Person speak");
            }
            public void eat() {
                System.out.println("Person eat");
            }
        }
    
        static class Dancer extends Person implements IDance {
    //        @Override
    //        public String toString() {
    //            return "I'm a Dancer";
    //        }
            @Override
            public void speak() {
                System.out.println("Dancer speak");
            }
            public void dance() {
                System.out.println("Dancer dance");
            }
        }
    
        static class Snake implements IDance {
            @Override
            public String toString() {
                return "I'm a Snake";
            }
            public void dance() {
                System.out.println("Snake dance");
            }
        }
    
        public static void main(String[] args) {
            IDance dancer = new Dancer();
            System.out.println(dancer);
            dancer.dance();
            //dancer.speak();
            //dancer.eat();
            IDance snake = new Snake();
            System.out.println(snake);
            snake.dance();
        }
    }
    

    执行结果如下:
    这里写图片描述
    可以看到System.out.println(dancer); 调用的是Person的toString方法。
    内存模型如下所示:
    这里写图片描述

    结束语

    这篇博文讨论了invokevirtual和invokeinterface的内部实现的区别,以及override的实现原理。下一步,打算讨论下invokevirtual的具体实现细节,如:如何实现符号引用到直接引用的转换的?可能会看下OpenJDK底层的C++实现。

    参考资料

    展开全文
  • Java 方法调用的底层实现

    千次阅读 2020-08-04 11:24:25
    我们写的代码,经过编译、经过类加载的各种阶段,进入了JVM的运行时数据区。 但作为程序员真正关心的是代码的执行,代码的执行其实本质上市方法...接着,在我们的代码中,就是方法调用过程,所以了解方法在 JVM .

     

     

    我们写的代码,经过编译、经过类加载的各种阶段,进入了JVM的运行时数据区。

    但作为程序员真正关心的是代码的执行,代码的执行其实本质上是方法的执行,站在JVM 的角度归根到底还是字节码的执行。main 函数式 JVM指令执行的起点,JVM 会创建 main线程来执行main函数,以触发JVM一系列指令的执行,真正的把 JVM 跑起来。接着,在我们的代码中,就是方法的调用过程,所以了解方法在 JVM 中的调用是非常有必要的。

    方法调用的字节码指令

    关于方法的调用,Java 字节码共提供了5个指令,来调用不同类型的方法:

    • invokestatic 用来调用静态方法
    • invokespecial 用来调用私有实例方法、构造器及 super 关键字等
    • invokevirtual 用于调用非私有方法,比如 public 和 protected,大多数方法调用属于这一种
    • invokeinterface 和上面指令类似,不过作用域接口类
    • invokedynamic 用来调用动态方法

     

    非虚方法

    如果方法在编译期就确定了具体的调用版本,这个版本在运行时是可变的,这样的方法称为非虚方法。

    这不是完整内容,完整内容:http://www.19971001.com/article/33

     

     

    展开全文
  • 上篇博文java方法调用之重载、重写的调用原理(一) 讨论了重写与重载的实现原理,这篇博文讨论下单分派与多分派。单分派、多分派方法的接收者和方法的参数统称为方法的宗量。 根据分派基于宗量多少(接收者是一个宗...
  • Java方法调用的优先级问题

    千次阅读 2017-03-29 13:05:45
    实现Java多态性的时候,关于方法调用的优先级: 我们这样假设下,super(超类)、this(当前类对象)、show(方法)、object(对象),方法调用优先顺序: ①this.show(object)>②super.show(object)> ③this....
  • JAVA方法调用在内存中的实现

    千次阅读 2018-01-30 21:52:49
    java方法分配内存是在栈中实现。 栈有一个特点:先进后出,java中方法的调用即是进栈(push) 方法的结束就是出栈(pop) 接下来用一张内存图演示方法在内存JVM的调用 入栈顺序main->m1->m2->m3 出栈顺序 m3->...
  • JAVA方法调用过程(最详细的解释)

    千次阅读 2018-10-29 22:28:53
    弄清楚方法调用过程,对于我们学习java极为重要,下面是调用过程的详细描述: 1、编译器查看对象的声明类型和方法名。 编译器去寻找所有名字为f但参数类型不同的方法。例如可能存在方法f(int)和方法f(String),...
  • Java方法调用时传递参数问题

    千次阅读 2015-10-17 15:23:04
    我们都知道将参数传递给方法时有两种,第一种是按值调用(called by value)表示方法接收的是调用者提供的值,第二种是按引用传递(called by reference)
  • 前一段时间看了《深入理解JVM》第三部分虚拟机执行子系统的内容,看到了重载与重写在JVM层面的调用原理(详见8.3 方法调用一节),但是没有写成博客总结一下,这里讨论讨论。在讨论过程中,难免会涉及到 字节码指令 ...
  • dalvik对于Java方法调用的实现

    千次阅读 2011-05-17 14:48:00
    (入口一)字节码OP_INVOKE_ (汇编实现) 1.dvmResolveMethod:(C函数)决议方法的Method :方法名字字符串找ClassObject中Method 2.(设置调用环境)创建一个方法调用栈帧(设置参数) 3.分支----(汇编)...
  • 今天遇见一个面试题,java基础的东西。我竟然给忘了。。。写下来加深一下印象面试题:public class Test1 { public static void main(String[] args) { String a = new String("abc"); int b = 5; int...
  • Java 反射调用静态方法

    万次阅读 2018-06-07 13:17:40
    Java 反射调用静态方法 参考地址:Java 反射调用静态方法
  • Java调用Python程序方法总结

    万次阅读 多人点赞 2018-01-17 23:58:07
    本文为大家介绍如何java调用python方法,供大家参考。 实际工程项目中可能会用到Java和python两种语言结合进行,这样就会涉及到一个问题,就是怎么用Java程序来调用已经写好的python脚本呢,一共有三种方法可以...
  • Java动态调用方法

    万次阅读 2017-12-26 10:45:23
    public void function(String str) ... / /根据 str的值 调用相应的方法 } public void test() { / /code } 如str的值为test,就调用test方法 主要用到java反射机制,Class和Method这些类。
  • JAVA类之间方法调用

    万次阅读 多人点赞 2018-11-02 23:39:15
    JAVA类方法的调用一、静态方法调用其他方法:1. 静态方法调用非静态方法2.静态方法调用静态方法二、非静态方法调用其他方法1.非静态方法在同一类内调用其他方法2.非静态方法在不同类之间调用其他方法 注:调用方法...
  • 详解java虚拟机方法调用

    千次阅读 2018-06-01 14:48:57
    方法调用 方法调用并不等同于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程。 所有方法调用中的目标方法在Class文件里面都是一个常量池中...
  • C++调用Java方法

    万次阅读 2018-10-17 16:02:23
    最近在搞JNI那块,发现网上很多都是Java调用JNI,然后...另一种是Java调用了C++,然后在该调用的C++里又回调另外的一个Java方法。其实这两种方法(或其他方法),都是要用到 JNIEnv,有关JNI的讲解可查阅此文章http...
  • java 判断方法调用是否超时 设置方法调用的超时时间public class Test { public static void main(String[] args) { Executor executor=Executors.newSingleThreadExecutor(); FutureTask<String> future=new ...
  • lua调用java java调用lua

    千次阅读 2018-07-31 10:17:05
    查找并调用指定的 Java 方法 检查调用结果,并从 Java 方法获取返回值 将 Lua function 作为参数传递给 Java 方法Java 方法调用 Lua function GL 线程和 UI 线程的协调 Lua function 的...
  • Java RMI远程方法调用详解

    万次阅读 多人点赞 2016-07-22 17:45:43
    远程方法调用RMI(Remote Method Invocation),是允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。 这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同...
  • Java远程方法调用

    千次阅读 2013-01-26 10:09:29
    主要参考 ... http://bbs.chinaunix.net/thread-1179312-1-1.html ...Java 远程处理  ... Java远程方法调用(RMI)提供了Java程序语言的远程通讯功能,这种特性使客户机上运行的程序可以调用远程服务器上的对象,使Java

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 173,257
精华内容 69,302
关键字:

java方法调用

java 订阅