java安全沙箱之class文件检验器,读完之后,大部分程序员收藏了.
bigegpt 2024-10-12 06:13 8 浏览
简介
jvm的.class文件检验器用于检查.class文件是否拥有合法的内存结构,这种检查是有必要的,因为java的.class文件可能来自本机,也可能来自网络,可能是你自己编译的文件,也可能是别人篡改过的文件。而对于jvm来说,一个.class文件就是一个字节序列,它不会过问字节序列的来源,只会校验字节序列的结构是否正确。
.class文件检验器保证安全的措施就是检验.class文件字节码的健壮性,比如某个.class文件是被恶意篡改过的,这个.class文件中包含一个方法,该方法有一条goto指令,直接跳到方法外部去执行未知的代码,如果执行该方法,很可能会导致jvm崩溃。所以,由.class文件检验器检查字节码的健壮性是很有必要的。
虽然.class文件检验器检查字节码能保证程序的健壮性,然后这是需要牺牲一些性能的;为了将这种影响降到最低,.class文件检验器会在字节码执行之前完成大部分的检验工作,也就是说,.class文件检验器会在字节码执行前而不是执行中进行检查,而且这种检查只会进行一次。比如每次遇到一条跳转指令.class文件检验器都会确认该跳转指令跳转到了另外一条合法指令,而该指令是是在同一方法的字节流中的。
.class文件检验器会进行四次独立的扫描来保证字节码的合法性。第一趟扫描在类装载时进行,这次会检查.class文件的内部结构,以保证它能被安全的编译;第二趟和第三趟扫描是在连接时进行的,这时会检查.class文件的数据定义是否遵从了java语言的语义规范,还会检查字节码的完整性;第四趟扫描是在解析符号引用时进行的,这次会检查.class文件所引用的字段、方法和类是否存在。
第一趟扫描
在.class文件被装载时,会进行第一次扫描,这时.class文件检验器会检查每一条字节序列,看它是否符合java class文件的基本结构。首先,检验器会检查.class文件是否以魔数0XCAFEBABY开头,这个魔数的作用是为了区分一些明显错误的或被破坏的.class文件。然后,检验器会检查.class文件的主版本号和次版本号,这个版本号必须在jvm所支持的范围之内,比如我用java8编译编译的.class文件放在java6的jvm内执行会抛出java.lang.UnsupportedClassVersionError,因为java6不支持java8的一些新特性比如lambda表达式,所以不能去执行java8的编译器编译的字节码;然后java一般都是向后兼容的,比如java8的jvm是能执行java6编译的.class文件的。第一趟扫描主要是检查.class文件是否遵从了java class文件的固定格式,这样才能字节码编译成方法区内的内部数据结构。
第二趟扫描
第二趟扫描会进行数据类型的语义检查,它不会再去检查.class文件的二进制数据了,而是会去检查方法区中定义的数据结构。类中定义的字段、方法和方法描述符等在.class文件中都会存储为一个字符串,检验器会检查这些字符串是否符合java规范;检验器还会检查类本身是否符合java语言规范,比如java语言规定除了Object类外所有类都必须有一个父类;检查器还会检查被final修饰的类(比如String.class)是否被继承,同样也会检查被final修饰的方法是否被覆盖,如果出现错误会抛出java.lang.VerifyError。检验器还会检查常量池里定义的常量是否合法,它会检查常量的索引会指向正确的常量池条目。
第三趟扫描
第三趟扫描会进行字节码验证,字节码检查会确认字节码的操作码的正确性,也会确保操作数栈包含正确的数值和类型,还会检查类的方法被调用时会传入正确的参数和参数类型。检验器在第三趟扫描会进行大量的操作,比如会检验所有的操作码都有一个合法的操作数等,在这趟扫描过后,它需要保证.class文件的字节码流可以被jvm安全地执行。然后检验器并不能检查出所有的安全问题,比如“停机问题”它就不能检查出来。停机问题是一个著名的计算机领域问题,即不能写出一个程序,用它来判断作为其输入的某个程序在执行时是否会停机。
第四趟扫描
第四趟扫描是在符号的动态连接时进行检查,检验器会检查符号引用是否合法;因为这次扫描需要检查该class类所引用的类,所以这是可能需要装载新的类;然而为了节约内存并保证程序正确性,jvm会使用延迟加载的策略来装载类,即直到类被程序真正使用时才会去装载。如果一个jvm实现为了加快装载速度预先装载了类,它还是会表现为延迟装载。比如jvm在预装载某个类时发现这个类不存在,它并不会马上抛出NoClassDefFoundError,而是直到这个缺少的类被程序使用时才抛出异常。如果jvm进行预先连接,第四次扫描会紧接着第三次扫描立刻执行;而如果jvm进行延迟连接(即在某个引用第一次执行时才连接),那么第四趟扫描可能在第三趟扫描之后很久才执行(甚至不执行)。
关注
感谢阅读,如果这篇文章帮助了您,欢迎 点赞 ,收藏,关注,转发 哟。您的帮助是我们前行的动力,我们会提供更多有价值的内容给大家... 谢谢!
相关推荐
- Go语言泛型-泛型约束与实践(go1.7泛型)
-
来源:械说在Go语言中,Go泛型-泛型约束与实践部分主要探讨如何定义和使用泛型约束(Constraints),以及如何在实际开发中利用泛型进行更灵活的编程。以下是详细内容:一、什么是泛型约束?**泛型...
- golang总结(golang实战教程)
-
基础部分Go语言有哪些优势?1简单易学:语法简洁,减少了代码的冗余。高效并发:内置强大的goroutine和channel,使并发编程更加高效且易于管理。内存管理:拥有自动垃圾回收机制,减少内...
- Go 官宣:新版 Protobuf API(go pro版本)
-
原文作者:JoeTsai,DamienNeil和HerbieOng原文链接:https://blog.golang.org/a-new-go-api-for-protocol-buffer...
- Golang开发的一些注意事项(一)(golang入门项目)
-
1.channel关闭后读的问题当channel关闭之后再去读取它,虽然不会引发panic,但会直接得到零值,而且ok的值为false。packagemainimport"...
- golang 托盘菜单应用及打开系统默认浏览器
-
之前看到一个应用,用go语言编写,说是某某程序的windows图形化客户端,体验一下发现只是一个托盘,然后托盘菜单的控制面板功能直接打开本地浏览器访问程序启动的webserver网页完成gui相关功...
- golang标准库每日一库之 io/ioutil
-
一、核心函数概览函数作用描述替代方案(Go1.16+)ioutil.ReadFile(filename)一次性读取整个文件内容(返回[]byte)os.ReadFileioutil.WriteFi...
- 文件类型更改器——GoLang 中的 CLI 工具
-
我是如何为一项琐碎的工作任务创建一个简单的工具的,你也可以上周我开始玩GoLang,它是一种由Google制作的类C编译语言,非常轻量和快速,事实上它经常在Techempower的基准测...
- Go (Golang) 中的 Channels 简介(golang channel长度和容量)
-
这篇文章重点介绍Channels(通道)在Go中的工作方式,以及如何在代码中使用它们。在Go中,Channels是一种编程结构,它允许我们在代码的不同部分之间移动数据,通常来自不同的goro...
- Golang引入泛型:Go将Interface「」替换为“Any”
-
现在Go将拥有泛型:Go将Interface{}替换为“Any”,这是一个类型别名:typeany=interface{}这会引入了泛型作好准备,实际上,带有泛型的Go1.18Beta...
- 一文带你看懂Golang最新特性(golang2.0特性)
-
作者:腾讯PCG代码委员会经过十余年的迭代,Go语言逐渐成为云计算时代主流的编程语言。下到云计算基础设施,上到微服务,越来越多的流行产品使用Go语言编写。可见其影响力已经非常强大。一、Go语言发展历史...
- Go 每日一库之 java 转 go 遇到 Apollo?让 agollo 来平滑迁移
-
以下文章来源于GoOfficialBlog,作者GoOfficialBlogIntroductionagollo是Apollo的Golang客户端Apollo(阿波罗)是携程框架部门研...
- Golang使用grpc详解(golang gcc)
-
gRPC是Google开源的一种高性能、跨语言的远程过程调用(RPC)框架,它使用ProtocolBuffers作为序列化工具,支持多种编程语言,如C++,Java,Python,Go等。gR...
- Etcd服务注册与发现封装实现--golang
-
服务注册register.gopackageregisterimport("fmt""time"etcd3"github.com/cor...
- Golang:将日志以Json格式输出到Kafka
-
在上一篇文章中我实现了一个支持Debug、Info、Error等多个级别的日志库,并将日志写到了磁盘文件中,代码比较简单,适合练手。有兴趣的可以通过这个链接前往:https://github.com/...
- 如何从 PHP 过渡到 Golang?(php转golang)
-
我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗旨,从零开始,开始学习。因为我司没有专门的Golang大牛,所以我也只能一步步自己去...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- libcrypto.so (74)
- linux安装minio (74)
- ubuntuunzip (67)
- vscode使用技巧 (83)
- secure-file-priv (67)
- vue阻止冒泡 (67)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)