交通银行23春招 软开 面经 您所在的位置:网站首页 银行春招一般几月份 交通银行23春招 软开 面经

交通银行23春招 软开 面经

2023-03-13 08:30| 来源: 网络整理| 查看: 265

交通银行23春招 软开 面经 一面

文章目录 1、面试流程、形式、题目2、题目分析1. 你了解的Java集合框架有哪些?2. 说到了list那list中有哪些类型?3. map又有哪些类型?5. hashmap的原理是什么?6. 现在先要存储一个对象进入hashmap该如何操作,原理是什么?7. 说一说线程安全问题?8. 既然提到了锁那么你对锁的升级有了解吗?9. 能讲讲jvm的垃圾回收机制吗?10. 那么什么情况会使用引用计数法,什么时候使用标记等方法呢?11. 你了解分代收集方法吗?12. 如果老年代中对象存储也满了会用什么方法来解决?13. 说一说堆内存中一般存储哪些数据?14. 你平时在开发过程中有用一些工具了解过程序运行时内存的情况吗?15. 看你项目中提到了使用了redis中间件,那么说一说redis支持的几种数据类型? 3、总结

1、面试流程、形式、题目

网申提交简历,由于校内招聘会所以是半线下面试,总共3位面试官,一个hr两位技术老师,hr在现场,两位技术老师远程腾讯会议。 先自我介绍,然后提问

面试问题:

你了解的Java集合框架有哪些?说到了list那list中有哪些类型?map又有哪些类型?hashmap的原理是什么?现在先要存储一个对象进入hashmap该如何操作,原理是什么?说一说线程安全问题?既然提到了锁那么你对锁的升级有了解吗?能讲讲jvm的垃圾回收机制吗?那么什么情况会使用引用计数法、标记法呢?你了解分代收集方法吗?如果老年代中对象存储也满了会用什么方法来解决?说一说堆内存中一般存储哪些数据?你平时在开发过程中有用一些工具了解过程序运行时内存的情况吗?看你项目中提到了使用了redis中间件,那么说一说redis支持的几种数据类型? 2、题目分析 1. 你了解的Java集合框架有哪些?

  Java集合框架是Java标准库提供的一组接口和类,用于管理和操作数据集合。Java集合框架包括以下几种类型的集合:

List:继承自 Collection 接口,List是一种有序的集合,它允许存储重复的元素。Java集合框架提供了ArrayList、LinkedList、Vector等实现List接口的类。Set:继承自 Collection 接口,Set是一种不允许存储重复元素的集合。Java集合框架提供了HashSet、TreeSet等实现Set接口的类。Queue:Queue是一种先进先出(FIFO)的队列,它允许在队尾插入元素,在队头删除元素。Java集合框架提供了LinkedList、PriorityQueue等实现Queue接口的类。Map:Map是一种键值对的映射表,它允许通过键来获取值。Java集合框架提供了HashMap、TreeMap等实现Map接口的类。 2. 说到了list那list中有哪些类型?

在Java的List接口中,有多个具体的实现类,主要包括以下三种:

ArrayList (Object[]数组,单线程性能佳) ArrayList是最常用的一种List实现,它通过一个数组来存储元素,支持快速随机访问,可以根据索引快速获取元素。它的添加和删除操作比较慢,因为需要移动数组中的元素。ArrayList是线程不安全的,不适合在多线程环境下使用,如果需要在多线程环境下使用,应该使用Vector或者CopyOnWriteArrayList。Vector(Object[]数组,多线程性能佳) Vector是线程安全的List实现,它的操作方法和ArrayList基本一致,但是Vector支持在多线程环境下安全地访问和修改,因为它的方法都是同步的。因此,如果需要在多线程环境下使用List,应该使用Vector而不是ArrayList。但是由于同步会影响性能,Vector在单线程环境下的性能比ArrayList差。 前两者的差异: 1、Vector是线程安全的,ArrayList不是线程安全的。 2、ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。 查看底层源码可知:无一例外,只要是关键性的操作,Vector的方法前面都加了synchronized关键字,来保证线程的安全性。当执行synchronized修饰的方法前,系统会对该方法加一把锁,方法执行完成后释放锁,加锁和释放锁的这个过程,在系统中是有开销的,因此,在单线程的环境中,Vector效率要差很多(多线程环境不允许用ArrayList,需要做处理)。 LinkedList LinkedList是基于链表的List实现,支持快速添加和删除操作,但是访问元素的效率比较低。LinkedList还实现了Deque接口,可以作为栈或队列使用。LinkedList是线程不安全的,不适合在多线程环境下使用。 与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。除了上述三种List实现外,还有一些其他的List实现,例如CopyOnWriteArrayList,它是一种线程安全的List实现,能够在并发环境下高效地进行读操作和写操作。此外,还有一些其他的List实现,例如Stack和VectorStack等,这些实现都是基于List接口,提供了不同的特性和功能。 3. map又有哪些类型?

  Java中的Map是一种键值对的数据结构,用于存储一系列不同类型的键和值。 常用的Java Map类有:

HashMap - 这是最常用的Map实现类,它使用哈希表来存储键值对。在HashMap中,键和值可以为null,并且不保证元素的顺序。因为哈希表的查询效率非常高,所以HashMap在大部分情况下都是最优选择。TreeMap - 这是基于红黑树的有序Map实现类。它按照键的自然顺序(或Comparator指定的顺序)来排序,因此具有有序性。在TreeMap中,键不能为null。由于TreeMap的实现方式,因此它的查询效率比HashMap低,但是可以快速地进行范围查找。LinkedHashMap - 这是继承自HashMap的实现类,它保留了插入顺序。在LinkedHashMap中,元素的顺序是按照插入顺序排序的。LinkedHashMap可以用于实现LRU缓存。WeakHashMap - 这是一种特殊的Map实现类,它的键为弱引用。当一个键不再被引用时,WeakHashMap会自动删除该键所对应的键值对,这样可以避免内存泄漏。WeakHashMap主要用于缓存一些临时对象。EnumMap - 这是专门用于枚举类型的Map实现类,它的键必须是同一枚举类型的枚举常量。由于枚举类型的数量有限,因此EnumMap使用了数组来存储键值对,具有非常高的效率。 除了以上常用的Map类之外,Java还提供了一些其他的Map实现类,如ConcurrentHashMap、IdentityHashMap、Properties等。不同的Map类适用于不同的场景,根据实际需求选择合适的Map类非常重要。 5. hashmap的原理是什么?

HashMap基于哈希表实现,可以高效地进行键值对的添加、删除和查找操作。 HashMap的原理:

存储结构: 数组:HashMap的底层存储结构是一个数组,数组的每个元素称为桶(bucket)。每个桶可以存储一个或多个键值对。数组的长度通常是2的整数次幂,这样可以保证通过哈希函数计算得到的哈希值可以直接对数组长度取模得到桶的索引。链表/红黑树:当不同的键值对经过哈希函数计算得到的哈希值相同时,它们会被存储在同一个桶中,这就可能会导致哈希冲突。为了解决哈希冲突,HashMap使用链表或红黑树来存储在同一个桶中的键值对。  在Java 8之前,HashMap使用的是单向链表来存储键值对。当桶中的元素较少时,使用链表存储可以快速添加和删除元素。但当桶中元素较多时,链表的查找时间复杂度为O(n),效率较低。因此,Java 8引入了红黑树来代替链表,这样可以在桶中元素较多时提高查找效率。当链表中的元素个数达到一定阈值(默认为8)时,HashMap会将链表转换为红黑树。 哈希函数:HashMap使用hashCode()方法计算键的哈希值,将哈希值与数组长度进行取模运算,得到对应的哈希桶下标。解决哈希冲突:由于不同的键可能具有相同的哈希值,因此会出现哈希冲突的情况。HashMap采用链地址法和红黑树来解决哈希冲突。在链地址法中,每个哈希桶存储一个链表,当新的键值对哈希到同一个桶时,将其添加到链表的末尾。在红黑树中,当链表的长度达到一定阈值(默认为8)时,将链表转换为红黑树,以提高查询效率。扩容:当HashMap中的元素个数超过了负载因子(默认为0.75)乘以数组长度时,HashMap会自动进行扩容。扩容操作会创建一个新的数组,将所有键值对重新哈希,并重新分配到新的桶中。扩容会导致性能下降,因此应该尽量预估元素数量,避免频繁扩容。线程安全:HashMap不是线程安全的,多个线程同时对HashMap进行修改可能导致不一致的结果。可以使用ConcurrentHashMap来实现线程安全的Map操作。 总之,HashMap通过哈希表实现高效的Map操作。但是在使用HashMap时,需要注意哈希函数的选择、哈希冲突的解决、负载因子的设置等问题,以充分发挥其优势。 6. 现在先要存储一个对象进入hashmap该如何操作,原理是什么?

计算对象的哈希值:

HashMap需要根据键的哈希值来确定该键值对在哈希表中的位置,因此需要先计算对象的哈希值。可以通过对象的hashCode()方法来获得哈希值。根据哈希值计算桶的索引:将哈希值对桶数组的长度取模,得到该键值对在哈希表中的桶的索引。在桶中查找键值对:如果桶中已经有键值对,则需要遍历桶中的键值对,找到与该键值对的键相等的键值对,如果找到则更新其值,否则添加新的键值对。如果桶中没有键值对,则直接将新的键值对插入到桶中。如果插入新键值对后,桶中的元素数量超过了阈值,就需要将链表转换为红黑树。 在上述步骤中,第二步是关键的一步,也是HashMap的核心原理之一。由于哈希冲突的存在,不同的键值对可能会映射到同一个桶中,因此需要通过哈希函数将键均匀地映射到桶中,并通过链表/红黑树来解决哈希冲突。通过这种方式,HashMap能够高效地实现键值对的插入、删除和查找操作。 7. 说一说线程安全问题?

  线程安全问题是指在多线程并发执行的情况下,多个线程同时访问共享资源时可能出现的问题。线程安全问题可能导致程序出现意料之外的行为,比如数据丢失、数据错乱、死锁等。 常见的线程安全问题有:

竞态条件(Race condition):当多个线程同时访问同一个共享资源,并且对这个资源的读写操作顺序没有被正确地同步时,就可能出现竞态条件。这种情况下,程序的输出结果可能随着不同的执行顺序而发生变化,从而导致错误的行为。死锁(Deadlock):当多个线程同时持有一些资源,并且每个线程都在等待其他线程释放自己所需要的资源时,就会发生死锁。这种情况下,所有的线程都被阻塞,无法继续执行,程序就会停止运行。数据竞争(Data race):当多个线程同时对同一个共享变量进行读写操作时,就可能发生数据竞争。这种情况下,由于没有对共享变量的访问进行同步,不同的线程可能会对同一个变量进行互相干扰的操作,导致程序出现错误。 为了避免线程安全问题,通常会采用各种技术来对共享资源进行同步,比如使用锁、信号量、互斥量等。同时,为了提高程序的并发性能,也可以采用一些无锁的算法来避免锁的竞争。

Java中提供了多种方式来解决线程安全问题,比较常用的方法有:

使用synchronized关键字:synchronized可以保证同一时刻只有一个线程访问被保护的代码块或方法。在Java中,每个对象都有一个锁(或称为监视器),只有获取到这个锁的线程才能执行被保护的代码。synchronized关键字可以用在方法或代码块中,并且可以用于不同的访问级别(如private、protected、public)。使用ReentrantLock:ReentrantLock是Java中提供的一个可重入锁实现。它提供了更灵活的锁机制,可以实现更复杂的同步需求。相对于synchronized,ReentrantLock可以提供更多的功能,比如公平锁、可中断锁、可定时锁等。使用Atomic类:Atomic类提供了一组原子操作,这些操作在多线程并发执行时保证了操作的原子性,避免了数据竞争问题。例如,AtomicInteger可以原子地递增或递减一个整数。使用ThreadLocal:ThreadLocal是Java中的一个线程本地变量,它为每个线程提供了一个独立的变量副本,避免了线程间共享变量的问题。ThreadLocal一般用于保证线程安全的单例模式、避免在多线程环境下出现共享变量的数据竞争等。使用Concurrent集合类:Java中的Concurrent集合类(如ConcurrentHashMap、ConcurrentLinkedQueue等)是专门为多线程并发访问而设计的。它们提供了高效的并发访问方式,避免了在多线程环境下出现线程安全问题的可能。 8. 既然提到了锁那么你对锁的升级有了解吗?

在Java中,锁可以分为偏向锁、轻量级锁和重量级锁三种,这些锁的升级过程如下:

偏向锁:当一个线程第一次访问一个对象时,偏向锁会把该对象的标记设置为当前线程,并且记录下线程的ID。此后,如果同一个线程再次访问该对象,就不需要竞争锁了,直接获取该对象的锁。如果其他线程访问该对象,则偏向锁会被撤销,转化为轻量级锁。轻量级锁:当多个线程竞争同一个对象的锁时,会出现锁的争夺。为了避免每个线程都要阻塞等待锁的释放,JVM提供了轻量级锁机制。当一个线程尝试获取锁时,JVM会使用CAS操作(Compare And Swap)来尝试获取锁。如果CAS成功,则该线程获取到了轻量级锁,并且可以执行同步操作。如果CAS失败,则说明其他线程已经获取了锁,此时该线程会进行自旋(也就是在循环中尝试获取锁),直到获取锁或者自旋次数达到一定的限制。如果自旋失败,则锁会被升级为重量级锁。 自旋锁:自旋锁是一种轻量级锁,在多个线程竞争同一个锁时,它会让线程在循环中自旋等待锁的释放,而不是让线程阻塞等待。这样可以减少线程的上下文切换,提高程序的性能。自旋锁适用于锁竞争时间短、线程数不多的情况。 重量级锁:当多个线程尝试获取同一个对象的锁,并且自旋多次之后仍然无法获取到锁时,JVM会将锁升级为重量级锁。重量级锁会让其他线程阻塞等待,直到当前线程释放锁之后才能获取锁。 互斥锁:互斥锁是一种重量级锁,在多个线程竞争同一个锁时,它会让其他线程阻塞等待,直到当前线程释放锁之后才能获取锁。互斥锁适用于锁竞争时间长、线程数较多的情况。 读写锁:读写锁是一种多读单写的锁,它可以提高多线程程序的并发性能。读写锁允许多个线程同时读取共享资源,但只允许一个线程写入共享资源,从而避免了写写冲突和读写冲突。原子锁:原子锁是一种基于硬件指令实现的锁,通过原子性操作来保证共享资源的互斥访问。原子锁可以避免线程的上下文切换和死锁问题,从而提高程序的并发性能和安全性。信号量:信号量是一种多线程同步机制,通过信号量来协调多个线程对共享资源的访问。信号量可以实现多个线程的同步和互斥访问,从而提高程序的安全性和并发性能。 需要注意的是,锁的升级是不可逆的,一旦锁被升级,就无法降级。另外,锁的升级过程是由JVM自动完成的。 9. 能讲讲jvm的垃圾回收机制吗?

  Java虚拟机(JVM)是一个具有自动内存管理功能的平台。 JVM使用垃圾回收机制来自动管理内存,这样程序员就不必手动释放内存了。当Java程序创建对象时,JVM会在堆中为对象分配内存。当对象不再被使用时,JVM会将其标记为垃圾,并在以后的某个时间释放内存。

引用计数法: (Java中并不使用) 一种简单的垃圾回收算法,它记录每个对象被引用的次数,并在引用计数为0时将其回收。但是,引用计数法有很多缺点,其中最严重的是循环引用问题。基于可达性分析的垃圾回收算法:为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。 标记-清除算法(Mark-and-Sweep):这是最基本的垃圾回收算法之一。它将堆分成两个区域:标记区和清除区。当对象被创建时,它被放置在标记区。当对象不再被使用时,垃圾收集器将标记对象,并将其移动到清除区。然后,清除区中的所有对象都将被释放。复制算法(Copying):这种算法将堆分成两个区域:一个存储活动对象,另一个存储垃圾。当垃圾回收器运行时,它将活动对象复制到垃圾区域,然后清除活动对象的存储区。这种算法的优点是,它可以快速回收垃圾,并且不需要进行复杂的标记操作。标记-整理算法(Mark-and-Compact):这种算法将垃圾收集器的工作分为两个阶段。首先,垃圾收集器会标记出所有活动对象,然后将它们移动到堆的一端。然后,垃圾收集器会将所有活动对象之外的空间释放出来,使堆中所有活动对象连续存放。分代收集算法(Generational):这种算法将堆分为几个区域,每个区域都有不同的生命周期。通常将堆分为两个区域:年轻代和老年代。年轻代存放的是新创建的对象,老年代存放的是存活时间较长的对象。垃圾收集器会频繁地回收年轻代,但很少回收老年代,因为老年代中的对象通常存活的时间比较长,且回收它们的代价比较高。 10. 那么什么情况会使用引用计数法,什么时候使用标记等方法呢?

  JVM并不使用引用计数法进行垃圾回收,而是使用基于可达性分析的垃圾回收算法。引用计数法是一种简单的垃圾回收算法,它记录每个对象被引用的次数,并在引用计数为0时将其回收。但是,引用计数法有很多缺点,其中最严重的是循环引用问题。   循环引用指的是两个或多个对象互相引用,但它们之间没有任何其他可达对象时。在这种情况下,引用计数法无法识别这些对象为垃圾对象,因为它们的引用计数永远不为0。这就导致了内存泄漏问题,因为这些对象将一直存在于内存中,无法被回收,造成内存泄漏。   其次是内存开销问题,引用计数法需要为每个对象维护一个计数器,这会增加内存开销。   因此,JVM使用基于可达性分析的垃圾回收算法来解决循环引用问题。这种算法从一组根对象开始,找出所有可以从根对象到达的对象,这些对象被认为是活动对象,其他对象被认为是垃圾对象。这种算法能够解决循环引用问题,并且在处理复杂的对象图时表现良好。

11. 你了解分代收集方法吗?

  JVM分代收集是一种针对不同对象存活时间的内存管理策略,根据对象的生命周期将Java堆分为不同的区域,并采用不同的垃圾回收算法进行管理。一般来说,Java堆分为新生代和老年代两个区域,其中新生代又分为Eden空间、Survivor 0空间和Survivor 1空间。   新生代中的对象通常存活时间较短,因此采用复制算法进行垃圾回收,即将新生代分为一个较大的Eden空间和两个较小的Survivor空间,然后将Eden空间中的对象进行垃圾回收,将存活的对象移动到其中一个Survivor空间中,当该Survivor空间被填满时,将其中存活的对象移动到另一个Survivor空间中,同时清空该Survivor空间。当某个Survivor空间中的对象经过多次垃圾回收后仍然存活,就会被移动到老年代中。(一般默认计数15)   老年代中的对象通常存活时间较长,因此采用标记-清除算法或标记-整理算法进行垃圾回收,即在垃圾回收之前先对所有活动对象进行标记,然后清除所有未标记的对象。标记-整理算法在清除对象时会将所有存活的对象移动到一个连续的内存区域中,这样可以避免出现内存碎片的问题。   分代收集机制可以有效地提高内存管理的效率和性能,因为它针对不同生命周期的对象采用不同的垃圾回收算法,同时也可以降低垃圾回收的频率和开销。分代收集机制在JVM中得到了广泛的应用,也是JVM默认的内存管理策略。

12. 如果老年代中对象存储也满了会用什么方法来解决?

  如果老年代中对象存储空间也满了,就需要采用更为复杂的垃圾回收算法来解决内存不足的问题。常见的解决方法有如下两种:   如果老年代中的对象存储空间也满了,可以通过增加老年代的空间来缓解内存不足的问题,或者使用分区回收算法对老年代进行更细粒度的管理。

分区回收算法: 一种针对老年代内存区域的垃圾回收算法。该算法通过将老年代分为多个大小相等的内存区域(也称为分区),每个分区独立管理,分别进行垃圾回收,从而降低整体垃圾回收的开销。   将老年代分为三个区域:Eden区、Survivor区和Tenured区。其中,Eden区和Survivor区一起组成了新生代,用于存储新创建的对象。Tenured区则用于存储长时间存活的对象。   在分区回收算法中,垃圾回收器会在Eden区和Survivor区之间建立一个内存复制区域(也称为To区),用于存放从Eden区和Survivor区中存活下来的对象。当Eden区或Survivor区中的对象达到一定数量时,就会触发垃圾回收器的垃圾回收操作。 具体流程如下: 当Eden区满时,会触发Minor GC,将Eden区和Survivor区中存活下来的对象复制到To区,并清空Eden区和Survivor区。对Survivor区进行标记-清除操作,清除无用对象。将To区和Survivor区交换,To区成为下一次GC时的Survivor区。 在分区回收算法中,每个分区都有自己的垃圾回收统计信息和阈值,可以根据需要进行调整,以提高垃圾回收效率和性能。

  需要注意的是,分区回收算法仅适用于老年代的垃圾回收,新生代使用的是复制算法。分区回收算法可以有效地减少整体垃圾回收的开销,但也带来了一定的空间浪费,因为分区之间需要留出一定的空间,以便进行对象移动。因此,在实际应用中,需要根据具体情况选择合适的垃圾回收算法和参数配置。   需要注意的是,由于老年代中的对象生命周期较长,因此不同于新生代,采用标记-整理算法可能会导致大量的对象移动,从而引起较大的性能开销。因此,当老年代中的对象存储空间也满了时,一般建议增加堆内存的大小,或者采用更加高级的垃圾回收算法来解决内存不足的问题。

13. 说一说堆内存中一般存储哪些数据?

在Java堆中,存储的数据和对象包括:

对象实例:通过new操作符创建的对象实例会存储在Java堆中。Java堆内存会根据对象的大小进行动态扩展。数组:Java数组也会存储在Java堆中。Java数组可以是基本类型的数组,也可以是对象数组。实例变量:每个对象实例都有自己的一组实例变量。实例变量也会存储在Java堆中。

在Java虚拟机中,内存分为以下几个区域:

程序计数器(Program Counter Register):线程私有,用于记录当前线程执行的字节码指令地址。Java虚拟机栈(Java Virtual Machine Stacks):线程私有,用于存储Java方法的局部变量、操作数栈、方法出口等信息。本地方法栈(Native Method Stack):线程私有,用于存储Java方法调用本地方法的相关信息。Java堆(Java Heap):Java虚拟机管理的内存区域,用于存储对象实例和数组。堆是Java虚拟机所管理的最大的一块内存区域,也是垃圾回收的主要区域。方法区(Method Area):线程共享的内存区域,用于存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码等。运行时常量池(Runtime Constant Pool):方法区的一部分,用于存储编译时期生成的各种字面量和符号引用。直接内存(Direct Memory):不是JVM运行时数据区的一部分,但是在JDK 1.4之后,Java提供了NIO(New Input/Output)类,可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。 需要注意的是,Java堆、方法区和直接内存被视为JVM运行时数据区,其中Java堆是JVM所管理的最大的一块内存区域,也是垃圾回收的主要区域。Java虚拟机栈、本地方法栈、程序计数器和运行时常量池等区域则主要是线程私有的。

Java栈中,存储的数据和对象包括:

局部变量:方法中定义的局部变量都存储在Java虚拟机栈中。局部变量包括基本数据类型、对象引用以及this引用等。操作数栈:操作数栈也称为操作栈,是一种后进先出(LIFO)的栈结构,用于存储方法执行过程中的操作数、中间结果等信息。方法出口:方法出口是指方法执行完毕后返回结果的地址。在Java虚拟机栈中,方法出口也被存储在栈帧中。 需要注意的是,Java虚拟机栈是线程私有的,每个线程都有自己的Java虚拟机栈。在方法执行过程中,Java虚拟机会为每个方法分配一个栈帧,栈帧中包含了方法执行所需要的数据和信息。当方法执行完毕后,栈帧会被弹出,Java虚拟机栈会恢复到上一个栈帧的状态。由于Java虚拟机栈是有限制的,如果线程在执行过程中需要的栈空间超过了Java虚拟机栈的最大限制,就会抛出StackOverflowError异常。如果Java虚拟机栈内存无法继续分配,则会抛出OutOfMemoryError异常。

常量池中,存储的数据和对象包括:

字面量:Java程序中所有的字符串字面量、数字字面量以及其他类型的字面量都会被编译成常量,并存储在运行时常量池中。符号引用:符号引用是指用来定位类、方法或字段的符号,包括类和接口的全限定名、方法的名称和描述符、字段的名称和类型等信息。运行时常量池中的常量池项:常量池项是指运行时常量池中存储的一个个常量。常量池项包括字面量常量、符号引用常量、方法类型常量、方法句柄常量、InvokeDynamic常量等。 需要注意的是,运行时常量池是与Java堆内存分开管理的。在Java虚拟机中,每个类都有自己的运行时常量池,用于存储该类所需要的常量。在Java程序运行过程中,Java虚拟机会动态地加载和卸载类,因此每个类的运行时常量池也会随着类的加载和卸载而发生变化。同时,Java虚拟机还提供了一些指令用于操作运行时常量池,例如ldc、ldc_w、ldc2_w等。

方法区中,存储的主要数据包括:

类信息:已加载类的完整信息,包括类名、父类名、接口列表、常量池、字段信息、方法信息等。静态变量:(全局变量)已被加载的类的静态变量,也称为类变量,存储在类的常量池中。常量:字面量和符号引用,包括字符串常量、基本数据类型常量、类和接口的全限定名、字段和方法的名称和描述符等。即时编译器编译后的代码:包括HotSpot虚拟机的即时编译器(JIT)编译后的本地代码和调用表。运行时常量池:每个类都有一个运行时常量池,用于存放该类运行时常量池中的字面量和符号引用。 需要注意的是,方法区的内存空间不受Java虚拟机的自动内存管理机制控制,因此当方法区内存不足时,可能会导致内存溢出错误。在JDK8及之前的版本中,方法区使用永久代来实现内存分配,而在JDK8之后,永久代被元空间取代。无论是永久代还是元空间,都是一块与Java堆分离的内存区域。 14. 你平时在开发过程中有用一些工具了解过程序运行时内存的情况吗?

常用的工具:

jstat命令:用于监控Java虚拟机的内存使用情况,可以实时查看堆内存和非堆内存的使用情况,以及类加载器的使用情况等。jmap命令:用于生成Java虚拟机进程内存快照,并提供详细的内存分析报告,包括堆内存的使用情况、对象数量、大小等信息。jvisualvm工具:是一个可视化的Java虚拟机监控和分析工具,可以监控应用程序的CPU、内存、线程和垃圾回收等性能指标,并提供堆内存和非堆内存的实时使用情况。Eclipse Memory Analyzer Tool (MAT):是一个基于Eclipse平台的内存分析工具,可以对Java堆转储文件进行分析,以识别内存泄漏、对象保留和重复对象等问题。VisualGC工具:是一个可视化的Java虚拟机垃圾回收监控工具,可以实时监控Java虚拟机的垃圾回收器的使用情况,包括各个垃圾回收器的运行时间、频率、内存使用情况等信息。 15. 看你项目中提到了使用了redis中间件,那么说一说redis支持的几种数据类型?

Redis支持5种基本数据类型,包括:

字符串(Strings):最基本的数据类型,支持字符串、整数、浮点数等。哈希表(Hashes):类似于关联数组或哈希表,存储键值对的映射。列表(Lists):存储有序的字符串列表,支持在头部和尾部插入和删除元素。集合(Sets):无序的字符串集合,支持并集、交集、差集等操作。有序集合(Sorted Sets):有序的字符串集合,每个元素都有一个分数,可以按照分数排序,支持按照排名、分数范围等进行查询。 除了这些基本数据类型,Redis还支持一些高级数据类型,例如: 布隆过滤器(Bloom Filters):用于判断一个元素是否在集合中存在,可以高效地进行去重和快速查找。地理位置(Geo):支持存储地理位置信息,可以根据经纬度查询附近的位置信息。流(Streams):一种新的数据类型,类似于消息队列,支持多个消费者同时消费消息。 3、总结

  一面其实问的很基础,基本上根据简历所写进行技术提问,所以一定要会什么写什么,但是面试官会根据你的回答继续深入,问着问着就会走到基础和底层原理,拔出萝卜带出泥,一直问到你哑口无言为止。过程中不知道一些知识点可以尽量说出自己的相关理解,但是不能瞎说。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有