《Java学习指南》—— 1.4 设计安全

本节书摘来异步社区《Java学习指南》一书中的第1章,第1.4节,作者:【美】Patrick Niemeyer , Daniel Leuck,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.4 设计安全

Java被设计为一种安全语言,对于这一事实你肯定早已耳熟能详了。但是在此“安全”指的是什么呢?对什么而言安全,或者对谁安全呢?对于Java,得到颇多关注的安全性是那些使新型动态可移植软件成为可能的有关特性。Java提供了多层保护以避免恶意代码,并防止诸如病毒和特洛伊木马等更具危险性的东西。在下一节中,我们将查看Java虚拟机体系结构如何在代码运行前评估其安全性,还将介绍Java类加载器(Java解释器的字节码加载机制)如何在不可信类周围加筑围墙。这些特性为高级安全性策略提供了基础,从而可以在每个应用的基础上允许或禁止各种操作。

不过,在本节中,我们将了解Java编程语言的一些通用特性。较之于特定的安全特性,Java通过解决通用设计和编程问题所提供的安全性可能更为重要,但在安全性讨论中这一点往往被忽视了。Java力图做到尽可能安全,即不仅要“抵制”我们自己所犯的简单错误,而且还要避免由原有软件所遗传的错误。Java的目标是保持语言的简单性,并提供展示其有用性的工具,同时令用户可以在需要时基于该语言构建更为复杂的功能。

1.4.1 语法简单性

Java有着简单性的原则。因为Java出身清白,它可以避免那些在其他语言中已经证实为糟糕或有争议的那些特性。例如,Java不允许程序员自定义操作符重载(overloading),而在某些语言中,允许程序员重新定义+和-这样的基本操符号的含义。Java没有源代码预处理器,因此没有宏、#define语句或条件源编译。这些在其他语言中存在的构造主要是为了支持平台依赖性,因此从这个意义上讲,它们在Java中是不需要的。条件编译通常还用于调试,但是Java的高级运行时优化以及断言这样的功能,较为优雅地解决了该问题。(我们将在第4章中讨论有关内容)。

Java为组织类文件提供了一个定义良好的包结构。此包系统允许编译器处理传统make实用工具的某些功能(make是用于将源代码构建为可执行代码的一个工具)。编译器还可以直接处理已编译Java类,因为所有类型信息都得到了保留;在此无需“头文件”,这一点与C或C++ 有所不同。所有这些都意味着Java代码需要读取的上下文环境信息更少。实际上,你有时可能会发现查看Java源代码比参考类文档更为快捷。

对于在其他语言中遭遇麻烦的一些特性,Java则将其取而代之。例如,Java只支持单一的类继承层次体系(每个类只能有一个“父”类),但是允许对接口多重继承。接口类似于C++ 中的一个抽象类,可以指定一个对象的多个操作,但是不会定义其实现,这是一个功能强大的机制,它允许开发者为对象定义一个“契约”,任何具体的对象实现都可以使用并引用该契约。Java中的接口消除了类的多重继承需求,同时不会导致与多重继承相关的问题。在第4章中你将会看到,Java是一种简单而又优雅的编程语言,而这仍然是它最大的吸引力。

1.4.2 类型安全和方法绑定

语言的一大属性是其采用何种类型检查。一般地,在将一种语言划归为“静态”或“动态”时,我们所指的是:有关变量类型的信息究竟是在编译时更多地得到明确,还是直至应用运行时方能更多地加以确定。

在诸如C或C++ 这样的严格静态类型语言中,数据类型在编译源代码时即已固化。这有利于编译器得到足够的信息,从而在代码执行前就能捕获多种错误,例如,编译器不会允许你在一个整数变量中保存一个浮点值。这样,代码将不再需要运行时类型检查,因此可以编译为小而快速的可执行代码。但是静态类型语言不够灵活。它们不能支持诸如集合的高级构造,而这些构造对于带有动态类型检查的语言则相当自然,另外对于静态类型语言而言,应用在运行时也不可能安全地导入新的数据类型。

与此相反,诸如Smalltalk或Lisp等动态语言则有一个运行时系统,可以管理对象的类型,并在应用执行时完成必要的类型检查。这些语言允许更为复杂的操作,另外在许多方面,其功能也更为强大。不过,它们往往速度较慢,不太安全,同时也较难调试。

语言之间的差别可以比作不同汽车之间的差别1。静态类型语言(如C++)可以比作跑车,相当安全,速度也很快,但是只有在柏油大道上才能很好地奔驰。动态性很好的语言(如Smalltalk)则更像是越野车:它们可以提供更大的自由度,但是稍难操控。也许在丛林里驾驶着它驰骋相当有趣(有时也更快),但是有时则未免会陷入壕沟或者遭到熊的袭击。

语言的另一个属性是采用何种方式将方法调用绑定至其定义。在诸如C或C++这样的语言中,方法的定义通常在编译时绑定,除非程序员特别指出。Smalltalk则有所不同,它被称为是一种“延迟绑定”(late-binding)语言,因为它在运行时才会动态地确定方法的定义。出于性能方面的原因,早期绑定(early-binding)相当重要;如此可以运行应用,而不会有运行时搜索方法所带来的开销。但是延迟绑定更为灵活。另外在面向对象语言中,这也是必要的,在此子类可以覆盖其超类中的方法,而且只有运行时系统才能确定应当运行哪个方法。

Java博采了C++ 和Smalltalk的优点,它是一种静态类型、延迟绑定的语言。Java中的每个对象都有一个编译时即已确定的定义良好的类型。这说明,Java编译器可以像是在C++中一样,完成同样的静态类型检查和使用分析。因此,你无法给对象赋予错误的变量类型,也不能在一个对象上调用不存在的方法。更有甚者,Java编译器还可以防止使用未初始化的变量以及创建不会执行的语句(请见第4章)。

不过,Java同时也完全可以做到在运行时确定类型。Java运行时系统会跟踪所有对象,并使得在执行时确定其类型和关系成为可能。这说明,可以在运行时检查一个对象以确定它究竟是什么。与C或C++不同的是,将一种对象类型强制转换为另一种类型时,要由运行时系统加以检查,而且有可能使用新型的动态加载对象(具有一定类型安全性的)。另外,由于Java是一种延迟绑定语言,一个子类总是有可能覆盖其超类中的方法,即使这是一个运行时加载的子类。

1.4.3 递增开发

Java从其源代码中将所有数据类型和方法签名信息带入到其编译后的字节码形式中。这就意味着,Java类可以递增地进行开发。你自己的Java类也可以安全地与来自于其他来源(编译器从未见过此来源)的类一同使用。换句话说,可以编写新的代码来引用二进制类文件,而不会丢失从源代码所得到的类型安全性。

困扰C++ 的一个常见问题是“脆弱基类”问题(fragile base class)。在C++ 中,由于一个基类有多个派生类,因此其实现可能被有效地“冻结”了;修改基类可能需要重新编译所有的派生类。对于类库的开发人员来说,这个问题尤其困难。Java通过在类中动态地定位字段,从而避免了这一问题。只要类维护了其原始结构的一个合法形式,那么就可以对其加以改进,而不会对由该类派生或使用了该类的其他类造成破坏。

1.4.4 动态内存管理

Java和C(C++)这样的低级语言之间的一些最为重要的差别涉及到Java如何管理内存。Java取消了可以引用内存的任意部分的临时的指针,并且为语言增加了垃圾回收和高级数组。这些特性消除了有关安全性、可移植性和优化的许多问题,否则这些问题将很难解决。

垃圾回收本身就可以使无数的程序员免于进行显式的内存分配和释放,而这在C或C++ 中也最容易导致错误。除了在内存中维护对象外,Java运行时系统还记录了对这些对象的所有引用。只要某个对象不再使用,Java即会自动地将其从内存中删除。你只需在不再使用对象时将其忽略,并确信解释器在适当的时候会予以清除。

Java使用了一个复杂的垃圾回收器,它在后台间歇性地运行,这意味着大多数垃圾回收工作均发生在空闲时间里,即介于I/O暂停、鼠标点击或按键之间。高级的运行时系统(如HotSpot)则可完成更高级的垃圾回收工作,甚至可以区分对象的使用模式(如对短期对象和长期对象加以区别),并且可以优化其收集过程。Java运行时现在可以自动调整自身,以便针对不同的应用程序,根据其行为来优化内存的分配。通过这种运行时探查,自动化的内存管理比最勤奋的程序员所管理的资源也要快很多,而某些老派的程序员仍然对此难以置信。

你可能听说过Java没有指针。严格地说,这种说法是正确的,但是它也会带来误导。Java所提供的是引用(reference),这是一种“安全型”指针,而且在Java中,引用是相当普遍的。引用是对象的一个强类型句柄。除了基本数字类型之外,Java中的所有对象都可以通过引用来访问。如果必要的话,可以使用引用来构建所有一般的数据结构,如链表、树等等,对于这些数据结构,以往C程序员惯用的做法是采用指针来构建。唯一的区别在于利用引用必须以一种类型安全的方式来操作。

在引用和指针间还有一个重要的区别,即无法通过引用更改其值(执行指针的算术运算)。引用只能指向特定的对象或某个数组中的元素。引用是一个原子性事物;除非将引用赋给一个对象,否则无法操作引用的值。引用采用传值方式传递,而且引用一个对象时,间接层不能多于一层。对引用的保护是Java安全性中最基本的一个方面。这说明,Java代码必须“按规章办事”,即不得“越权”行事。

不同于C或C++ 指针,Java引用只能指向类的类型。在此不存在指向方法的指针。人们有时会对此有所抱怨,但是你会发现,若任务需要方法指针,那么大多数时候,采用接口和适配器类会更为漂亮地将其完成。另外还需提到一点,Java有一个复杂的“反射(reflection)”API,这确实允许你引用和调用单个的方法。不过,这并不是常规做法。我们将在第7章讨论反射。

最后,Java中的数组是真正的头等(first-class)对象。它们可以像其他对象一样动态地分配和赋值。数组知道其自己的大小和类型,而且尽管你无法直接定义或派生数组类的子类,但是基于其基类型的关系,它们确实有一个定义良好的继承关系。语言中若拥有真正的数组,则可以消除C或C++等语言中对指针算术运算的需求。

1.4.5 错误处理

Java的出发点在于网络化设备和嵌入式系统。对于这些应用,拥有健壮而且智能的错误管理机制是至关重要的。Java有一个强大的异常处理机制,这一点有些类似于C++ 的最新实现。异常提供了一个更为自然和优雅的方式来处理错误。异常可以将错误处理代码从一般的代码中分离出来,从而得到更为简洁、更具可读性的应用。

出现一个异常时,将导致程序执行流程转移到一个提前指定的“捕获”代码块。异常附带有一个对象,其中包含有导致出现异常的情形的相关信息。Java编译器要求方法所声明的异常要么是其能够生成的,要么是可以自行捕获和处理的。这将错误信息的重要性,提高到与参数(argument)和返回类型相同的层次。作为一个Java程序员,应当清楚地知道哪些异常情况需要处理,而且编译器还有助于你编写正确的软件,从而不会让这些异常“放任自流”而未加处理。

1.4.6 线程

如今的应用都需要高度的并行性。即使一个非常简单的应用也可能有一个复杂的用户界面,而这就需要并发的活动。随着机器速度越来越快,用户对于为完成无关任务而占用时间的现象也越来越敏感。线程为客户和服务器应用提供了高效的多处理和任务分配机制。Java使得线程很易于使用,因为其对线程的支持是内置于语言中的。

并发性固然很好,但是采用线程编程所做的不仅仅是同时完成多项任务。在大多数情况下,线程需要得到同步(协调),如果没有显式的语言支持则会相当棘手。Java基于监视器和条件模型可以支持同步,这是一种用于访问资源的加锁和钥匙系统。关键字synchronized指定方法和代码块要在对象内得到安全、串行化的访问。也存在一些简单的基本方法,从而可以在对同一对象加以处理的线程之间显式地等待和标记。

Java还有一个高级的并发包,它提供了强大的工具来解决多线程编程中的常见模式,例如,线程池、任务的协调以及复杂的锁定。通过这个并发包和相关的工具,Java提供了一些比任何其他语言都更为高级的线程相关工具。

尽管一些开发者可能永远不必编写多线程代码,但学习使用线程编程,是掌握Java编程的一个重要部分,这是所有程序员都应该掌握的内容。参见第9章关于这个主题的更多讨论。

1.4.7 可伸缩性

在最低的层次上,Java程序由类组成。类被设计为小型的模块化组件。在类之上,Java提供了包,这是一个结构层,它将类分组为功能单元。包为类的组织提供了一个命名约定,另外还对Java应用中变量和方法的可见性提供了另一级组织控制。

在一个包中,类可以是公开可见的,也可能有所保护以避免外部访问。包构成了另一种类型的作用域,它与应用级更为接近。这有助于构建能够在系统中协同工作的可复用组件。包还有助于设计一个可伸缩的应用,从而在扩展应用时,代码不至于过于相互依赖。

a6da19bc0d49ee2863c12ccb6f6aa99303519097

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/541503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ppython_Python pcom包_程序模块 - PyPI - Python中文网

PCOM在python中一个非常基本的unitronics pcom协议实现。如何使用from pcom import commandsfrom pcom.plc import EthernetPlcwith EthernetPlc(address(192.168.5.43, 1616)) as plc:# Read realtime clockc commands.ReadRtc()res plc.send(c)print(res)# Set realtime cl…

bitcount方法详解_Java Long类的bitCount()方法和示例

bitcount方法详解长类bitCount()方法 (Long class bitCount() method) bitCount() method is available in java.lang package. bitCount()方法在java.lang包中可用。 bitCount() method is used to find the number of 1s bits in the 2s complement binary denotation of the…

《软件定义数据中心:Windows Server SDDC技术与实践》——导读

前言 通过对自身的审视和对身边IT 技术专家的观察,我发现对于我们来说,掌握一项新的技术或熟悉一个新的产品,大都是闻而后知,知而后学,学以致用,用以知其然。然而Windows Server作为一个简单的、易上手的操…

python二维向量运算模拟_python二维向量运算_[VB.NET][C#]二维向量的基本运算

前言在数学中,几何向量是指具有大小和方向的几何对象。在编程中,向量有着广泛的应用,其作用在图形编程和游戏物理引擎方面尤为突出。第一节 构造函数通过创建一个二维向量的类(或结构体),实现向量的表示及其运算。1. 首先&#xf…

Java LinkedHashMap clear()方法与示例

LinkedHashMap类的clear()方法 (LinkedHashMap Class clear() method) clear() method is available in java.util package. clear()方法在java.util包中可用。 clear() method is used to remove all the existing elements from this LinkedHashMap. clear()方法用于从此Link…

《Imperfect C++中文版》——1.3 运行期契约:前置条件、后置条件和不变式

本节书摘来自异步社区出版社《Imperfect C中文版》一书中的第1章,第1.3节,作者: 【美】Matthew Wilson,更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.3 运行期契约:前置条件、后置条件和不变式 Imperfect …

python名称空间与运用域_Python名称空间和作用域讲座,命名,Namespaces,Scopes

Python命名空间(Namespaces)和作用域(Scopes)讲座命名空间(Namespace)命名空间(Namespace),是名称到对象的映射。命名空间提供了在项目中避免名字冲突的一种方法。命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,…

getminimum_Java Calendar getMinimum()方法与示例

getminimumCalendar类的getMinimum()方法 (Calendar Class getMinimum() method) getMinimum() method is available in java.util package. getMinimum()方法在java.util包中可用。 getMinimum() method is used to get the minimum value of the given field(fi) of this Cal…

《Spark核心技术与高级应用》——3.2节构建Spark的开发环境

本节书摘来自华章社区《Spark核心技术与高级应用》一书中的第3章,第3.2节构建Spark的开发环境,作者于俊 向海 代其锋 马海平,更多章节内容可以访问云栖社区“华章社区”公众号查看 3.2 构建Spark的开发环境无论Windows或Linux操作系统&am…

python闭包怎么理解_Python 闭包的理解

Last Updated on 2019年10月15日Python中的闭包是一个比较模糊的概念,不太好理解,我最近的面试中也被问及,在一个单例模式的实现上,我用装饰器实现单例,然后面试官就问到了我对闭包的理解,回答的不太清楚。…

Java BufferedReader mark()方法与示例

BufferedReader类mark()方法 (BufferedReader Class mark() method) mark() method is available in java.io package. mark()方法在java.io包中可用。 mark() method is used to mark the current position in this stream and whenever we call reset() method so it will re…

《全球互联网金融商业模式:格局与发展》——第3章,第3节互联网保险公司...

本节书摘来自华章出版社《全球互联网金融商业模式:格局与发展》一书中的第3章,第3.3节互联网保险公司,作者廖理,更多章节内容可以访问云栖社区“华章计算机”公众号查看 3.3 互联网保险公司互联网思维贯穿整个保险创新发展过程&a…

webapi随机调用_BeetleX之webapi验证插件JWT集成

对于webapi服务应用很多时候需要制订访问限制,在前面的章节也讲述了组件如何制订控制器访问控制;但到了实际应用要自己去编写还是比较麻烦。为了让访问控制更方便组件实现基于JWT的控制器访问控制组件BeetleX.FastHttpApi.Jwt;通过这个组件可…

java bitset_Java BitSet nextClearBit()方法与示例

java bitsetBitSet类nextClearBit()方法 (BitSet Class nextClearBit() method) nextClearBit() method is available in java.util package. nextClearBit()方法在java.util包中可用。 nextClearBit() method is used to retrieve the index of the first bit that is set to …

《驯狮记——Mac OS X 10.8 Mountain Lion使用手册》——2.3 Dock

本节书摘来自异步社区《驯狮记——Mac OS X 10.8 Mountain Lion使用手册》一书中的第2章,第2.3节,作者:陈明 , 张铮 , 马玉龙著,更多章节内容可以访问云栖社区“异步社区”公众号查看 2.3 Dock 驯狮记——Mac OS X 10.8 Mountain…

mysql 嵌套if标签_对比Excel、MySQL、Python,分别讲述 “if函数” 的使用原理!

作者:黄伟呢本文转自:数据分析与统计学之美其实,不管是Excel、MySQL,还是Python,“if”条件判断都起着很重要的作用。今天这篇文章,就带着大家盘点一下,这三种语言如何分别使用 “if函数” 。if…

Java BigDecimal intValue()方法与示例

BigDecimal类的intValue()方法 (BigDecimal Class intValue() method) intValue() method is available in java.math package. intValue()方法在java.math包中可用。 intValue() method is used to convert a BigDecimal to an integer and when the converted BigDecimal val…

R语言数据挖掘

数据分析与决策技术丛书 R语言数据挖掘 Learning Data Mining with R [哈萨克斯坦]贝特麦克哈贝尔(Bater Makhabel) 著 李洪成 许金炜 段力辉 译 图书在版编目(CIP)数据 R语言数据挖掘 / (哈…

linux adduser mysql_linux_adduser

新帐号建立当不加-D参数,useradd指令使用命令列来指定新帐号的设定值and使用系统上的预设值.新使用者帐号将产生一些系统档案,使用者目录建立,拷备起始档案等,这些均可以利用命令列选项指定。此版本为RedHatLinux提供,可帮每个新加…

java iterator_Java ArrayDeque iterator()方法与示例

java iteratorArrayDeque类iterator()方法 (ArrayDeque Class iterator() method) iterator() Method is available in java.lang package. iterator()方法在java.lang包中可用。 iterator() Method is used to return an iterator over the deque elements. iterator()方法用于…