基础知识点

匿名 (未验证) 提交于 2019-12-03 00:27:02

JAVA中的常量池

在Java的内存分配中,总共3种常量池:

字符串常量池

Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid",另一种就是使用new这种标准的构造对象的方法,如String str = new String("droid"),这两种方式我们在代码编写时都经常使用,尤其是字面量的方式。然而这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池。

当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。

字符串常量池在Java内存区域的哪个位置

  • 在JDK6.0及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中;
  • 在JDK7.0版本,字符串常量池被移到了堆中了。至于为什么移到堆内,大概是由于方法区的内存空间太小了。

举例说明:

字面量创建形式

String str1 = "droid";

JVM检测这个字面量,这里我们认为没有内容为droid的对象存在。JVM通过字符串常量池查找不到内容为droid的字符串对象存在,那么会创建这个字符串对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量str1。

如果接下来有这样一段代码

String str2 = "droid";

同样JVM还是要检测这个字面量,JVM通过查找字符串常量池,发现内容为”droid”字符串对象存在,于是将已经存在的字符串对象的引用返回给变量str2。注意这里不会重新创建新的字符串对象。

验证是否为str1和str2是否指向同一对象,我们可以通过这段代码

System.out.println(str1 == str2);

结果为true。

使用new创建

String str3 = new String("droid");
当我们使用了new来构造字符串对象的时候,不管字符串常量池中有没有相同内容的对象的引用,新的字符串对象都会创建。因此我们使用下面代码测试一下,
String str3 = new String("droid"); System.out.println(str1 == str3);

结果如我们所想,为false,表明这两个变量指向的为不同的对象。

intern

对于上面使用new创建的字符串对象,如果想将这个对象的引用加入到字符串常量池,可以使用intern方法。

调用intern后,首先检查字符串常量池中是否有该对象的引用,如果存在,则将这个引用返回给变量,否则将引用加入并返回给变量。

String str4 = str3.intern(); System.out.println(str4 == str1);

输出的结果为true。

注意:字符串常量池中存放的是引用还是对象,这个问题是最常见的。字符串常量池存放的是对象引用,不是对象。在Java中,对象都创建在堆内存中。

举例说明:

String str2 = new String("str")+new String("01"); str2.intern(); String str1 = "str01"; System.out.println(str2==str1);
在JDK 1.7下,当执行str2.intern();时,因为常量池中没有“str01”这个字符串,所以会在常量池中生成一个对堆中的“str01”的引用(注意这里是引用 ,就是这个区别于JDK 1.6的地方。在JDK1.6下是生成原字符串的拷贝),而在进行String str1 = “str01”;字面量赋值的时候,常量池中已经存在一个引用,所以直接返回了该引用,因此str1和str2都指向堆中的同一个字符串,返回true。
String str2 = new String("str")+new String("01"); String str1 = "str01"; str2.intern(); System.out.println(str2==str1);
将中间两行调换位置以后,因为在进行字面量赋值(String str1 = “str01〃)的时候,常量池中不存在,所以str1指向的常量池中的位置,而str2指向的是堆中的对象,再进行intern方法时,对str1和str2已经没有影响了,所以返回false。

class常量池

我们写的每一个Java类被编译后,就会形成一份class文件;class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。

每个class文件都有一个class常量池。

运行时常量池

运行时常量池存在于内存中,也就是class常量池被加载到内存之后的版本

6种负载均衡算法:

1、轮询法

  将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。

2、随机法

3、源地址哈希法

4、加权轮询法

  不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。

5、加权随机法

6、最小连接数法


List用法

  • List继承了Collection,是有序的列表(逻辑顺序和物理顺序相同,随机访问)

ArrayList:

  • 基于数组实现的,是一个数组队列。可以动态的增加容量
  • 线程不安全

LinkedList:

  • 基于链表实现的,是一个双向循环列表。可以被当做堆栈使用
  • 线程不安全

Vector:

  • 基于数组实现的,是一个矢量队列
  • 添加了synchronized修饰,是线程安全的

Stack:

  • 基于数组实现的,是栈,它继承与Vector,特性是FILO(先进后出)

Map用法

HashMap:

  • 底层是哈希表数据结构
  • 可以存入null键和null值
  • 线程不安全

Hashtable:

  • 底层是哈希表数据结构
  • 不可以存入null键和null值
  • 线程安全的

TreeMap:

  • 底层是二叉树数据结构
  • 可以用于Map键排序(默认按key升序排序)
  • 线程不安全

类加载器

类加载器是负责将可能是网络上、也可能是磁盘上的class文件加载到内存中。并为其生成对应的java.lang.class对象。一旦一个类被载入JVM了,同一个类就不会被再次加载。那么怎样才算是同一个类?在JAVA中一个类用其全限定类名(包名和类名)作为其唯一标识,但是在JVM中,一个类用其全限定类名和其类加载器作为其唯一标识。也就是说,在JAVA中的同一个类,如果用不同的类加载器加载,则生成的class对象认为是不同的。

当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构

  • 启动类加载器BootstrapClassLoader

是嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负载加载JAVA_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。

  • 扩展类加载器ExtensionClassLoader

该加载器是用JAVA编写,且它的父类加载器是Bootstrap,是由sun.misc.Launcher$ExtClassLoader实现的,主要加载JAVA_HOME/lib/ext目录中的类库。开发者可以使用扩展类加载器。

我们知道java中系统属性java.ext.dirs指定的目录由ExtClassLoader加载器加载,如果程序中没有指定该系统属性(-Djava.ext.dirs=sss/lib)那么该加载器默认加载$JAVA_HOME/lib/ext目录下的所有jar文件,通过程序来看下系统变量java.ext.dirs所指定的路径:

public class Test {     public static void main(String[] args)     {         System.out.println(System.getProperty("java.ext.dirs"));     } }  执行结果: D:\ProgramFile\Java\jdk1.8.0\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
  • 系统类加载器App ClassLoader

系统类加载器,也称为应用程序类加载器,负责加载应用程序classpath目录下的所有jar和class文件。它的父加载器为Ext ClassLoader。

public class Test {     public static void main(String[] args)     {         System.out.println(ClassLoader.getSystemClassLoader());     } }  执行结果: sun.misc.Launcher$AppClassLoader@497470ed









































文章来源: 基础知识点
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!