jvm:java代码是如何运行的?
一、Java代码运行流程
A、基本流程
一个Java项目,包含很多的「.java」为后缀的源代码文件,除去IDE里直接执行调试,一般来说,都是把代码打成jar包,或者是war包,最后将打包好的jar包或是war包传到线上服务器部署。
部署方式很多,最基本的一种是通过Tomcat容器来部署,也可以是自己手动通过java命令来运行一个jar包中的代码。
B、编译
上述流程中有一个非常关键的点,「编译」。
在java代码打包的过程中,一般会把源代码编译成「.class」后缀的字节码文件。只有字节码文件class才能被JVM识别并解释运行。
C、JVM进程
对于编译好的class字节码,需要使用诸如java -jar之类的命令来运行写好的代码;一旦使用java命令,实际上此时就会启动一个JVM进程。
JVM进程会负责运行这些class字节码文件,也就相当于负责运行我们写好的代码。
D、类加载
JVM要运行这些class字节码文件中的代码,会采用类加载器把编译好的class字节码文件加载进JVM内存中
E、解释执行
最后JVM会基于自己的字节码执行引擎,来执行加载到内存里的类。当JVM需要哪个类时,会使用类加载器来加载对应的类。
从虚拟机的视角来看,执行java代码首先需要将它编译而成的class文件加载到java虚拟机中。加载后的java类会被存放在方法区中。实际运行时,虚拟机会执行方法区的代码。
在运行过程中,每当调用进入一个java方法,java虚拟机会在当前线程的java方法栈中生成一个栈帧,用以存放局部变量以及字节码的操作数。这个栈帧的大小是提前计算好的,而且java虚拟机不要求栈帧在内存空间里连续分布。
在hotspot里面,上述翻译过程有两种形式:第一种是解释执行,即逐条将字节码翻译成机器码并执行;第二种是即时编译(JIT),即将一个方法包含的所有字节码编译成机器码后再执行。
String存放在堆中还是栈中?
问题中的String指的应该是java中的String吧。这里给出的回答针对java。
String是一个不可变的对象,在java中只能作为常量使用。java代码中所有的显式字符串,即直接写出的那种字符串,例如"abc"都是String对象。String本身作为一个对象,必然是在堆上的,而String中的内容char[] value 则是放在堆中的一个特殊区域中——常量区。
所以String本身是放在堆上,而根据垃圾回收情况,又可以分为新生代和老年代。如果这个String对象刚创建不久,则它一般位于堆的新生代,如果它创建之后存在了很长时间,则它很可能处于堆中的老年代。注意,String中的字符串内容即字符数组value则位于堆中的常量区。
如果你先有一个字符数组,例如char[] arr { 'a', 'b', 'c' },然后调用String s = new String(arr);创建的String,则字符数组不再是位于常量区,而是跟其他对象一样,位于堆上。注意,即使这个arr数组是在栈上分配的,这样创建的String中的value依然是在堆上。如果你想把这个字符串放进常量区,可以调用String.intern。
栈上不会有对象,只会有基本变量和引用变量,所以String只可能位于堆上,不可能位于栈上。

