Class常量池

本文介绍Java字节码文件结构及其常量池的作用。解释了字节码文件如何存储字面量和符号引用,并展示了通过javap命令查看字节码的例子。此外,还介绍了常量池在不同JDK版本中的存储位置变化。

     Class常量池可以理解为是Class文件中的资源仓库。 Class文件中除了包含类的版本、字段、方法、接口等描述信息外, 还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。

一个class文件的16进制大体结构如下图:
在这里插入图片描述
对应的含义如下,细节可以查下oracle官方文档
在这里插入图片描述
当然我们一般不会去人工解析这种16进制的字节码文件,我们一般可以通过javap命令生成更可读的JVM字节码指令文 件:
javap -v Math.class

Classfile /E:/open/demo/target/classes/com/example/demo/test/opencv/Math.class
  Last modified 2020-9-20; size 619 bytes
  MD5 checksum f70c67abc97af9f0978a807380fcb072
  Compiled from "Math.java"
public class com.example.demo.test.opencv.Math
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#26         // java/lang/Object."<init>":()V
   #2 = Class              #27            // com/example/demo/test/opencv/Math
   #3 = Methodref          #2.#26         // com/example/demo/test/opencv/Math."<init>":()V
   #4 = Methodref          #2.#28         // com/example/demo/test/opencv/Math.compute:()I
   #5 = Class              #29            // java/lang/Object
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               LineNumberTable
  #10 = Utf8               LocalVariableTable
  #11 = Utf8               this
  #12 = Utf8               Lcom/example/demo/test/opencv/Math;
  #13 = Utf8               compute
  #14 = Utf8               ()I
  #15 = Utf8               a
  #16 = Utf8               I
  #17 = Utf8               b
  #18 = Utf8               c
  #19 = Utf8               main
  #20 = Utf8               ([Ljava/lang/String;)V
  #21 = Utf8               args
  #22 = Utf8               [Ljava/lang/String;
  #23 = Utf8               math
  #24 = Utf8               SourceFile
  #25 = Utf8               Math.java
  #26 = NameAndType        #6:#7          // "<init>":()V
  #27 = Utf8               com/example/demo/test/opencv/Math
  #28 = NameAndType        #13:#14        // compute:()I
  #29 = Utf8               java/lang/Object
{
  public com.example.demo.test.opencv.Math();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/example/demo/test/opencv/Math;

  public int compute();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: iconst_1
         1: istore_1
         2: iconst_2
         3: istore_2
         4: iload_1
         5: iload_2
         6: iadd
         7: bipush        10
         9: imul
        10: istore_3
        11: iload_3
        12: ireturn
      LineNumberTable:
        line 6: 0
        line 7: 2
        line 8: 4
        line 9: 11
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   Lcom/example/demo/test/opencv/Math;
            2      11     1     a   I
            4       9     2     b   I
           11       2     3     c   I

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #2                  // class com/example/demo/test/opencv/Math
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #4                  // Method compute:()I
        12: istore_2
        13: return
      LineNumberTable:
        line 14: 0
        line 15: 8
        line 16: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  args   [Ljava/lang/String;
            8       6     1  math   Lcom/example/demo/test/opencv/Math;
           13       1     2 compute   I
}
SourceFile: "Math.java"

常量池中主要存放两大类常量:字面量符号引用

字面量
字面量就是指由字母、数字等构成的字符串或者数值常量
字面量只可以右值出现,所谓右值是指等号右边的值,如:int a=1 这里的a为左值1为右值。在这个例子中1就是字面量。

int a = 1; 
int b = 2; 
int c = "abcdefg";

符号引用
符号引用是编译原理中的概念,是相对于直接引用来说的。主要包括了以下三类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符
         上面的a,b就是字段名称,就是一种符号引用,还有Math类常量池里的 Lcom/example/demo/test/opencv/Math 是类的全限定名, main和compute是方法名称,()是一种UTF8格式的描述符,这些都是符号引用。
          这些常量池现在是静态信息,只有到运行时被加载到内存后,这些符号才有对应的内存地址信息,这些常量池一旦被装 入内存就变成运行时常量池了,对应的符号引用在程序加载或运行时会被转变为被加载到内存区域的代码的直接引用, 也就是我们说的动态链接了。例如,compute()这个符号引用在运行时就会被转变为compute()方法具体代码在内存中 的地址,主要通过对象头里的类型指针去转换直接引用。

Jdk1.6及之前: 有永久代, 常量池在方法区
Jdk1.7:有永久代,但已经逐步“去永久代”,常量池在堆
Jdk1.8及之后: 无永久代,常量池在元空间

字符串常量池

字符串常量池的设计思想

  1. 字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建 字符串,极大程度地影响程序的性能
  2. JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化

为字符串开辟一个字符串常量池,类似于缓存区
创建字符串常量时,首先坚持字符串常量池是否存在该字符串
存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中

代码示例,一些字符串局部变量操作

String str1 = "abc"; 
String str2 = "abc"; 
String str3 = "abc"; 
String str4 = new String("abc");
String str5 = new String("abc");
String str5 = new String("abc");

在这里插入图片描述

安全点与安全区域

安全点

安全点就是指代码中一些特定的位置,当线程运行到这些位置时它的状态是确定的,这样JVM就可以安全的进行一些操作,比 如GC等,所以GC不是想什么时候做就立即触发的,是需要等待所有线程运行到安全点后才能触发。 这些特定的安全点位置主要有以下几种:

  1. 方法返回之前
  2. 调用某个方法之后
  3. 抛出异常的位置
  4. 循环的末尾

安全区域

Safe Point 是对正在执行的线程设定的。
如果一个线程处于 Sleep 或中断状态,它就不能响应 JVM 的中断请求,再运行到 Safe Point 上。 因此 JVM 引入了 Safe Region。
Safe Region 是指在一段代码片段中,引用关系不会发生变化。在这个区域内的任意地方开始 GC 都是安全的。 线程在进入 Safe Region 的时候先标记自己已进入了 Safe Region,等到被唤醒时准备离开 Safe Region 时,先检查能 否离开,如果 GC 完成了,那么线程可以离开,否则它必须等待直到收到安全离开的信号为止。

STM32 RSA加密解密项目概述STM32是一款基于ARM Cortex-M内核的微控制器,广泛应用于嵌入式系统中。在这个项目中,我们关注的是如何在STM32单片机上实现RSA2048算法,这是一种非对称加密技术,常用于保护数据的安全。RSA2048以其2048位的密钥长度,提供了极高的安全性,适用于敏感数据的传输和储。RSA算法基于数论中的两个大素数乘积的因数分解难题,其核心包括一对密钥:公钥和私钥。公钥可公开分发,用于加密数据;而私钥则需要保密,用于解密数据。在这个项目中,已经在了一套公钥和私钥,用于实际的加密和解密操作。项目结构与文件解释项目的文件结构如下:1. `clearAllGarbage.bat`:这是一个批处理文件,通常用于清理工作目录,删除不必要的文件。2. `Readme.txt`:包含了项目说明和指导,对于理解项目功能和使用方法至关重要。3. `Bsp`:板级支持包,包含针对STM32硬件平台的驱动程序和配置,如GPIO、UART等。4. `rsa`:这是实现RSA算法的核心代码库,可能包含加密和解密函数,以及PKCS#1填充方式的实现。5. `app`:应用程序代码,调用RSA库进行加密和解密操作,并通过串口将结果输出。6. `STM32F10x_FWLib`:STM32官方提供的固件库,提供了基本的外设驱动接口。7. `CORE`:包含Cortex-M内核相关的底层支持代码。8. `User`:用户应用代码,可能包含主函数和其他自定义功能。9. `Project`:Keil uVision工程文件,包含了编译和调试的配置。RSA在STM32上的实现在STM32上实现RSA2048,通常需要以下步骤:1. **移植OpenSSL库**:OpenSSL是一个强大的安全套接字层密码库,包含了多种加密算法,包括RSA。为了在STM32上使用RSA,需要将OpenSSL库裁剪并移植到MCU上,这涉及到内管理、优化和资源占用的考虑。2. **PKCS#1填充**:PKCS#1是RSA加密的标准填充模式,它增加了数据的随机性,提高加密的安全性。在这个项目中,采用的是PKCS1填充方式,以确保加密过程的正确性和安全性。3. **数据交互**:STM32通过UART串口与其他设备通信,发送和接收加密或解密的数据。UART接口需要正确配置波特率、奇偶校验等参数。4. **内管理**:RSA2048涉及的大数据量处理对内有较高要求。STM32的RAM资源有限,因此需要合理管理内,避免溢出。5. **编程和调试**:在Keil uVision环境中,开发者可以编写、编译、链接代码,并通过仿真器或硬件调试器进行调试,观察加密解密过程和结果。6. **性能优化**:由于STM32的计算能力有限,可能需要对RSA算法进行优化,例如使用硬件加速器或特定的数学库,来提升运算速度。这个项目展示了如何在资源受限的STM32单片机上实现RSA2048加密解密,这对于嵌入式系统的安全通信具有重要意义。通过阅读源代码和项目文档,开发者可以学习到RSA算法的实际应用,以及在微控制器环境下进行加密算法移植和优化的技巧。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值