JAVA JVM

jdk是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。
Java SE、Java EE和Java ME有什么区别?

Java现在已不仅仅是一种语言,从广义上说,它代表了一个技术体系。该体系根据应用方向的不同主要分为Java SE、Java EE和Java ME的3个部分。

1998年12月份Sun公司公布的Java 1.2版本,同时将它的名字改称为“Java 2软件开发工具箱1.2”。它的后续版本也通常被称为“Java 2标准版”(J2SE)。在J2SE的推出的同时,还推出了“Java 2微缩版”(J2ME)和“Java 2企业版”(J2EE)。

J2SE为创建和运行Java程序提供最基本环境,是Java技术的核心和基础。
J2EE为基于服务器的分布式企业应用提供开发和运行环境,是目前Java技术应用最广泛的部分。J2EE不仅继承了J2SE中的许多优点,同时还提供了对EJB、JSP、Servlet以及XML技术的全面支持,降低了企业级开发的复杂度。
J2ME为嵌入式应用提供开发和运行环境,例如手机程序和PDA程序等。
在Java 5.0(或者称为1.5)版本推出后,为了避免版本混淆,便将J2SE、J2EE和J2ME改称为Java SE 5、Java EE 5和Java ME 5,后续版本只变更相应版本号,例如Java EE 6。

1.java面试 JDK,JRE,JVM三者的区别

简单粗暴的理解
JDK包含了JRE,JRE包含了JVM

详解
JDK: java development kit, java开发工具包,用来开发Java程序的,针对java开发者。
JRE: java runtime environment, java运行时环境,针对java用户
JVM: java virtual machine,java虚拟机 用来解释执行字节码文件(class文件)的。
)
JVM 是什么
JVM:Java Virtual Machine(Java 虚拟机)JVM是JRE的一部分,它是一个虚拟出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。

JVM是Java实现跨平台最核心的部分,所有的Java程序会首先被编译为.class的类文件,JVM的主要工作是解释自己的指令集(即字节码)并映射到本地的CPU的指令集或OS的系统调用。Java面对不同操作系统使用不同的虚拟机,依次实现了跨平台。JVM对上层的Java源文件是不关心的,它关心的只是由源文件生成的类文件。

JRE是什么?
JRE:Java Runtime Environment(Java运行环境)。在Java平台下,所有的Java程序都需要在JRE下才能运行。只有JVM还不能进行class的执行,因为解释class的时候,JVM需要调用解释所需要的类库lib。JRE里面有两个文件夹bin和lib,这里可以认为bin就是JVM,lib就是JVM所需要的类库,而JVM和lib合起来就称为JRE。

JRE包括JVM和JAVA核心类库与支持文件。与JDK不同,它不包含开发工具—-编译器、调试器和其它工具。

JDK是什么?
JDK:Java Development ToolKit(Java开发工具包)。JDK是整个JAVA的核心,包括了Java的运行环境(Java Runtime Environment)、一堆Java工具(javac、java、jdb等)和Java基础的类库(即Java API包括rt.jar)。

Java API是Java的应用程序接口,里面有很多已经写好的Java Class,包括一些重要的语言结构以及基本图形,网络和文件I/O等等,我们可以直接调用使用。

现在已经有很多版本的JDK,除了Sun公司,还有很多公司都开发了属于自己的JDK,如IBM、淘宝等。据说IBM的JDK运行效率比Sun的还要高,但是不管怎么说还是先把基础的Sun JDK学好。

总结:

有JVM就可以解释执行字节码文件(.class).
JVM解释执行这些字节码文件的时候需要调用类库,如果没有这些类库JVM就不能正确的执行字节码文件,JVM+类库=JRE,
有了JRE就可以正确的执行java程序了,但是光有JRE不能开放Java程序,所以JRE+开发工具=JDK,有了JDK,就可同时开发,执行JRE.

两个JRE,都有什么作用?
我们平时开发Java程序的时候,都会同时安装JDK和JRE:

JDK里面的JRE安装路径:D:\dev\java\jdk1.8.0_91\jre
JDK外面的JRE安装路径:D:\dev\java\jre1.8.0_91
JDK里面的JRE是JDK自带的为其开发工具提供运行环境的JRE,在JDK中有很多用Java编写的开发工具(如: javac.exe、jar.exe),这些工具的实现代码在JDK下面的lib目录下的tools.jar中,也就是路径:D:\dev\java\jdk1.8.0_91\lib\tools.jar里面。

JDK外面JRE用于为Java程序提供运行环境。
两个JRE的异同
相同点:这两个JRE都可以作为开发Java程序的运行环境。
不同点:JDK自带的开发工具只能使用JDK自己目录下的JRE,不能使用JDK外面的JRE。
实际开发情况
我们开发的实际情况是:我们利用JDK(调用本地的API)开发属于自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,在JRE上运行这些JAVA字节码,JVM解释这些字节码,映射到CPU指令集或OS的系统调用。

二、基本概念

理解这两个概念非常重要。

内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。
(一个无用的对象一直占据在内存中)
内存溢出:指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。
从定义上可以看出内存泄露是内存溢出的一种诱因,不是唯一因素。

三、内存泄露的几种场景:

1、长生命周期的对象持有短生命周期对象的引用

        这是内存泄露最常见的场景,也是代码设计中经常出现的问题。

例如:在全局静态map中缓存局部变量,且没有清空操作,随着时间的推移,这个map会越来越大,造成内存泄露。

2、修改hashset中对象的参数值,且参数是计算哈希值的字段

         当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段,否则对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中删除当前对象,造成内存泄露。

3、机器的连接数和关闭时间设置
长时间开启非常耗费资源的连接,也会造成内存泄露。

四、内存溢出的几种情况:
四、内存溢出的几种情况:

1、堆内存溢出(outOfMemoryError:java heap space)

   在jvm规范中,堆中的内存是用来生成对象实例和数组的。

   如果细分,堆内存还可以分为年轻代和年老代,年轻代包括一个eden区和两个survivor区。

   当生成新对象时,内存的申请过程如下:

a、jvm先尝试在eden区分配新建对象所需的内存;

b、如果内存大小足够,申请结束,否则下一步;

c、jvm启动youngGC,试图将eden区中不活跃的对象释放掉,释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;

d、Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;

e、 当OLD区空间不够时,JVM会在OLD区进行full GC;

f、full GC后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”:

                               outOfMemoryError:java heap 

2、方法区内存溢出(outOfMemoryError:permgem space)

   在jvm规范中,方法区主要存放的是类信息、常量、静态变量等。

   所以如果程序加载的类过多,或者使用反射、gclib等这种动态代理生成类的技术,就可能导致该区发生内存溢出,一般该区发生内存溢出时的错误信息为:

         outOfMemoryError:permgem space

3、线程栈溢出(java.lang.StackOverflowError)

   线程栈时线程独有的一块内存结构,所以线程栈发生问题必定是某个线程运行时产生的错误。

   一般线程栈溢出是由于递归太深或方法调用层级过多导致的。

   发生栈溢出的错误信息为:

          java.lang.StackOverflowError

public class StackOverflowTest {

public static void main(String[] args) {

  int i =0;

digui(i);

}

private static void digui(int i){

  System.out.println(i++);

 String[] s = new String[50];

 digui(i);

}

}

五、为了避免内存泄露,在编写代码的过程中可以参考下面的建议:

1、尽早释放无用对象的引用

2、使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域

3、尽量少用静态变量,因为静态变量存放在永久代(方法区),永久代基本不参与垃圾回收

4、避免在循环中创建对象

5、开启大型文件或从数据库一次拿了太多的数据很容易造成内存溢出,所以在这些地方要大概计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。

3.简答jsp和servlet的联系和区别。

1.jsp经编译后就变成了Servlet.
(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
2.jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.
3.Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.
Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。
而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。

联系:
JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。
Servlet和JSP最主要的不同点在于:
Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。
而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。
JSP侧重于视图,Servlet主要用于控制逻辑
Servlet更多的是类似于一个Controller,用来做控制。

3、通过MVC双剑合璧

既然JSP和Servlet都有自身的适用环境,那么能否扬长避短,让它们发挥各自的优势呢?答案是肯定的——MVC(Model-View-Controller)模式非常适合解决这一问题。

MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller):

Controller——负责转发请求,对请求进行处理
View——负责界面显示
Model——业务功能编写(例如算法实现)、数据库设计以及数据存取操作实现
在JSP/Servlet开发的软件系统中,这三个部分的描述如下所示:

Web浏览器发送HTTP请求到服务端,被Controller(Servlet)获取并进行处理(例如参数解析、请求转发)
Controller(Servlet)调用核心业务逻辑——Model部分,获得结果
Controller(Servlet)将逻辑处理结果交给View(JSP),动态输出HTML内容
动态生成的HTML内容返回到浏览器显示
MVC模式在Web开发中的好处是非常明显,它规避了JSP与Servlet各自的短板,Servlet只负责业务逻辑而不会通过out.append()动态生成HTML代码;JSP中也不会充斥着大量的业务代码。这大大提高了代码的可读性和可维护性。
7.什么是存储过程?用什么来调用?
:存储过程是一个预编译的SQL语句,比如一些场景的sql比较复杂,并且需要经常使用或者多次使用的。存储过程的优点是说只需创建一次编译一次,以后在该程序中就可以多次直接调用。如果一个sql是经常需要操作的,并且逻辑不容易改变,使用存储过程比单纯SQL语句执行要快,因为sql每次查询而且都需要编译。而且网络开销也大,存储过程只需要传一个名字,在数据库调用就行了,而且这样程序可移植高。

JVM 内存分区:
Java 虚拟机在执行Java 程序的过程中会把它所管理的内在划分为若干个不同的数据区域。这些区域都各有用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁;

1.程序计数器

这是一块相对来说比较小的内存空间,它的作用是用来存储线程执行到哪个字节码的行号。程序运行时就是不断地执行字节码,不断地改变该空间中的存储的行号。在多线程环境中,由于每一个线程执行到的位置都不会时刻相同的,所以程序计数器保存的是每一条线程各自的字节码行号,也就是说,程序计数器是线程私有的。如果线程当前执行的是一个Java方法,那计数器记录的就是虚拟机字节码指令的地址;如果正在执行的是Native 方法,那这个计数器值则为空。(来自:《深入理解Java虚拟机》)

在执行Native 方法的时候计数器的值为空了,那有没有疑问它是怎么往下走的呢?都不知道下一步到哪行了。其实我也觉得它表达得不清楚,其实,在执行Native 方法的时候是新起一条线程来执行的,该条线程上的计数器值为空,这么说才对。原来的线程就会阻塞,直到执行Native 方法的那条线程完结后原来的线程才继续执行下去。

此内在区域是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError (内在溢出错误)情况的区域。(来自:《深入理解Java虚拟机》)

2.Java 虚拟机栈

虚拟机栈也是线程私有的,生命周期与线程相同。虚拟机栈是用于存储方法执行时所产生的:局部变量表、操作数栈、动态链接、方法出口等。

正如其名,该内存中所用到的数据结构就是栈,所有相关操作也就是栈的操作。上面所提到的存储内容就是存储在一个个的栈桢中的。每个方法都有自己的栈桢,栈桢入栈那就方法开始执行,出栈就是方法执行完成。栈是线程私有的嘛,每条线程都有自己的一条栈。在活动的线程中,只有栈顶的栈桢是有效的,称为当前栈。

局部变量表:编译期可知的各种基本数据类型(boolean 、byte、char、short 、int、float、long、double)、对象引用和returnAddress (指向了一条字节码指令的地址)。这些都是在编译的时候就确定的,虚拟机使用局部变量表完成参数值到参数变量列表的传递过程。也就是说,局部变量区是一个经字长为单位的数组,访问是通过索引进行的。如果是实例方法,那么局部变更表的第0位索引默认是用来传递方法所屋对象的实例的引用,在方法中通过this 访问。系统不会为局部变量赋予初始值,所以我们在方法中定义局部变量的时候一般都是要给它赋值的。

操作数栈:这个地方是干嘛用的呢,我们的变量有地方存了,但我们执行方法时临时的东西没地方放呢。比如一条计算公式:int i=0;i=3+4;3+4这一步是怎么算出来然后再赋值级i的呢,这就要靠操作数栈了。 操作数栈就是虚拟机的工作区。它虽说和局部变量区一样用的也是以字长为单位的数组,但它并不是靠索引来访问的,然后真正的栈操作--出栈各压栈(每一次都是在栈顶操作)。当解释到 i=3+4这一步时发现两个临时数值3、4,于是是把它两压到栈中,然后收到指令是加法运算,就是将3、4从栈中弹中进行运算,得到7把压入栈中,然后遇到要给i进行赋值的指令,再把7从栈中弹出放到局部变量区中去。通过以上形象的描述是不是明白了操作数栈的作用了啊。

动态链接:我们知道class 文件是源代码经过编译后得到的字节码。到了运行的时候再从字节码中取到类然后将其生成。何为动态链接,就是我用到哪个类,就将哪个类加载到内在中,在这里当然就是要用到哪个方法就加载哪个方法,如何定位到该方法呢,在一个叫常量池的地方保存着这个方法的符号引用,找到这个符号引用就能找到方法了,这个引用就是动态链接。

3.本地方法栈

本地方法栈发挥的作用与虚拟机栈是相似的,区别只是虚拟机栈是为Java 方法服务,而本地方法栈是为本地方法(native 方法)。有些虚拟机(比如 sun sotspot )就直接将本地方法栈与虚拟机栈合二为一了。

4.Java堆

堆是虚拟机中管理的最大的一块内在了。Java 堆被所有线程共享,它在虚拟机启动的时候就创建了。它只有一个目的,那就是存放对象的实例(包括数组)。堆的大小是可以扩展的,通过 -Xmx 和 Xms 来控制。(Xms 表示初始分配的堆内存,也就是程序初始化的时候,给你分配的堆内存的大小,Xmx 表示允许的最大的堆内存,也就是说堆内存不够的时候你给你继续分配,直到达到这个最大值为止,但无论怎么样,这个值都不应该超过物理上的内存值)

5.方法区

这个区域也是线程共享的,它存储着类的相关信息,常量,静态变量,即时编译后的代码等数据。

6.运行时常量池

运行时常量池是方法区的一部分。Class 文件除了有类的版本、字段、方法、接口等描述的信息名,还有一项信息是常量池,用来存放编译期生成的各种字面量和符号引用。这部分内容将在类加载后就进入方法区的运行时常量池中存放。(来自:《深入理解Java虚拟机》)

7.直接内存

在JDK1.4后加入一个NIO类,它是基于通道和缓冲区的I/O方式,它可以使用Native 函数库直接分配堆外面的内存,然后通过存储在堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。避免了Java 堆 和 Native 堆中来回复制数据。

相关文章:

  • 2021-04-19
  • 2021-10-14
  • 2022-12-23
  • 2021-04-03
猜你喜欢
  • 2021-08-04
  • 2021-05-11
  • 2022-01-18
  • 2021-04-26
  • 2021-09-24
  • 2021-09-15
  • 2021-11-27
相关资源
相似解决方案