点击围观!腾讯 TAPD 助力金融行业研发提效、敏捷转型最佳实践! 了解详情
写点什么

你应该远离的 6 个 Java 特性

  • 2013-11-12
  • 本文字数:2264 字

    阅读完需:约 7 分钟

Nikita Salnikov Tarnovski plumbr 的高级开发者,也是一位应用性能调优的专家,他拥有多年的性能调优经验。近日,Tarnovski撰文谈到了普通开发者应该尽量避免使用的 6 个 Java 特性,这些特性常见于各种框架或库当中,但对于普通的应用开发者来说,使用这些特性也许会给你所开发的应用带来灾难。

我曾花费了无数个小时为各种不同的应用排错。根据过往的经验我可以得出这样一个结论,那就是对于大多数开发者来说,你应该远离几个 Java SE 特性或是 APIs。这里所说的大多数开发者指的是一般的 Java EE 开发者而不是库设计者或是基础设施开发者。

坦白地说,从长远来看,大多数团队都应该远离如下的 Java 特性。不过凡事总有例外的情况。如果你有一个强大的团队,总是能够清楚地意识到自己在做什么,那就按照你的想法去做就行。但对于大多数情况来说,如果你在项目的开发中使用了下面这几个 Java 特性,那么从长远来看你是会后悔的。

这些应该远离的 Java 特性有:

  • 反射
  • 字节码操纵
  • ThreadLocal
  • 类加载器
  • 弱引用与软引用
  • Sockets

下面对这些特性进行逐个分析,看看为什么普通的 Java 开发者应该远离他们:

反射:在流行的库如 Spring 和 Hibernate 中,反射自然有其用武之地。不过内省业务代码在很多时候都不是一件好事,原因有很多,一般情况下我总是建议大家不要使用反射。

首先是代码可读性与工具支持。打开熟悉的 IDE,寻找你的 Java 代码的内部依赖,很容易吧。现在,使用反射来替换掉你的代码然后再试一下,结果如何呢?如果通过反射来修改已经封装好的对象状态,那么结果将会变得更加不可控。请看看如下示例代码:

如果这样做就无法得到编译期的安全保证。就像上面这个示例一样,你会发现如果 getDeclaredField() 方法调用的参数输错了,那么只有在运行期才能发现。要知道的是,寻找运行期 Bug 的难度要远远超过编译期的 Bug。

最后还要谈谈代价问题。JIT 对反射的优化程度是不同的,有些优化时间会更长一些,而有些甚至是无法应用优化。因此,有时反射的性能损失可以达到几个数量级的差别。不过在典型的业务应用中,你可能不会注意到这个代价。

总结一下,我觉得在业务代码中唯一合理(直接)使用反射的场景是通过 AOP。除此之外,你最好远离反射这一特性。

字节码操纵:如果在 Java EE 应用代码中直接使用了 CGLIB 或是 ASM 库,那么我建议你好好审视一下。就像方才我提到的反射带来的消极影响,使用字节码操纵所带来的痛苦可能是反射的好几倍之多。

更糟糕的是在编译期你根本就看不到可执行的代码。从本质上来说,你不知道产品中实际运行的是什么代码。因此在面对运行期的问题以及调试时,你要花费更多的时间。

ThreadLocal:看到业务代码中如果出现 ThreadLocal 会让我感到颤抖,原因有二。首先,借助于 ThreadLocal,你可以不必显式通过方法调用就可以传递变量,而且会对这种做法上瘾。在某些情况下这么做可能是合理的,不过如果不小心,那么我可以保证最后代码中会出现大量意想不到的依赖。

第二个原因与我每天的工作有关。将数据存储在 ThreadLocal 中很容易造成内存泄漏,至少我所看到的十个永久代泄漏中就有一个是由过量使用 ThreadLocal 导致的。连同类加载器及线程池的使用,“java.lang.OutOfMemoryError:Permgen space”就在不远处等着你呢。

类加载器:首先,类加载器是个很复杂的东西。你必须首先理解他们,包括层次关系、委托机制以及类缓存等等。即便你觉得自己已经精通了类加载器,一开始使用时还是会出现各种各样的问题,很可能会导致类加载器泄漏问题。因此,我建议大家还是将类加载器留给应用服务器使用吧。

弱引用与软引用:关于弱引用与软引用,你是不是只知道他们是什么以及简单的使用方式而已?现在的你对 Java 内核有了更好的理解,那会不会使用软引用重写所有的缓存呢?这么做可不太好,可不能手里有锤子就到处找鼓敲吧。

你可能很想知道我为什么说缓存不太适用使用软引用吧。毕竟,使用软引用来构建缓存可以很好地说明将某些复杂性委托给 GC 来完成而不是自己去实现这一准则。

下面来举个例子吧。你使用软引用构建了一个缓存,这样当内存行将耗尽时,GC 会介入并开始清理。但现在你根本就无法控制哪些对象会从缓存中删除,很有可能在下一次缓存中不再有这个对象时重新创建一次。如果内存还是很紧张,又触发 GC 执行了一次清理,那么很有可能会出现一个死循环,应用会占用大量 CPU 时间,Full GC 也会不断执行。

Sockets: java.net.Socket 简直太难使用了。我认为它的缺陷归根结底源自其阻塞的本质。在编写具有 Web 前端的典型的 Java EE 应用时,你需要高度的并发性来支持大量的用户访问。这时你最不想发生的事情就是让可伸缩性不那么好的线程池呆在那儿,等待着阻塞的 Sockets。

现在已经出现了非常棒的第三方库来解决这些问题,别自己写了,尝试一下 Netty 吧。

各位 InfoQ 读者,Java 出现至今经历了多次版本更迭,每次也都会有诸多新特性的加入。在日常的 Java 开发中,你认为存在哪些 Java 特性是很容易导致问题的呢?作者提到不建议在普通的应用开发中使用反射,不过对于一些框架或库的开发,离开反射实际上是无法实现的,例如 Spring、Struts2 等框架,那么在一般的 Java 项目开发中,你觉得哪些地方有使用反射的必要呢?换句话说,如果不使用反射就实现不了功能或是需求。文中作者也不建议使用字节码操纵,实际上一些框架在实现某些功能时是必须要使用的,比如说 Spring 在实现 AOP 时就使用了 Java 的动态代理与 CGLib 库两种方式来达成的。那么对于一般的 Java 项目来说,哪些地方需要用到字节码操纵呢?欢迎各位读者畅所欲言,一起讨论这些有趣的话题。

2013-11-12 12:297005
用户头像

发布了 88 篇内容, 共 253.7 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

乘着汽车智能化的浪潮,“汽车人”的职业方向选择(三)

SOA开发者

软件定义汽车 车载控制单元

为什么不推荐Python初学者直接看项目源码

Felix

Python 编程 开发 Programing 阅读代码

Percolator模型及其在TiKV中的实现

vivo互联网技术

数据库 Percolator 分布式,

2021年公有云市场的5大趋势

浪潮云

云计算

金融级分布式事务解决方案DTC

tom

Linux用户密码管理

在即

9月日更

主机安全是什么意思?安全体检包含哪些方面?

行云管家

运维 服务器 主机 主机安全 安全体检

幻读是啥,会有什么问题?如何解决?

Java MySQL 数据库 面试 后端

测试开发之前端篇-CSS层叠式样式表

禅道项目管理

CSS html

对Python爬虫编写者充满诱惑的网站,《可爱图片网》,瞧人这网站名字起的

梦想橡皮擦

9月日更

一部好看过武侠小说的热血互联网史!

博文视点Broadview

iOS开发面试拿offer攻略之数据结构与算法篇附加安全加密

iOSer

ios 数据加密 iOS面试 iOS逆向 iOS算法

深入理解掌握零拷贝技术

Linux服务器开发

网络协议 零拷贝 Linux服务器开发 Linux内核 用户态

JavaScript进阶(七)call, apply, bind

Augus

JavaScript 9月日更

玩转TypeScript工具类型(下)

有道技术团队

typescript 大前端 网易有道

我愿意招什么样的产品经理?

石云升

产品经理 招聘 9月日更

FunTester框架Redis性能测试之list操作

FunTester

redis 性能测试 测试框架 压力测试 FunTester

mydumper备份工具介绍与使用

Simon

MySQL

与springcloud整合的框架源码读取入口

Java 编程 架构 微服务

网络攻防学习笔记 Day144

穿过生命散发芬芳

高可用 9月日更

Tapdata 实时数据中台在智慧教育中的实践

tapdata

低代码应用:软件开发的一体化最新形态!

优秀

低代码

堡垒机作用之事后审计详细讲解-行云管家

行云管家

运维 网络安全 运维审计 事后审计

千万级数据迁移与分表的技术方案-企业产品实战

谙忆

Java 后端 分库分表 引航计划

通俗易懂 即时通讯初学者入门 WhatsApp技术架构

OpenIM

银行数字化转型指南:《区域性银行数字化转型白皮书》完整版重磅发布

百度开发者中心

最佳实践 银行数字化转型

Alibaba内部“Java架构核心宝典”来袭,全新技术限时开源

Java 编程 程序员 架构 面试

作为一线技术人员,如何更好地提升自己

谙忆

管理 成长 引航计划

基于Tensorflow + Opencv 实现CNN自定义图像分类

华为云开发者联盟

tensorflow KNN OpenCV CNN

二十不惑的年纪,我简直走了狗屎运(4面拿字节跳动offer)

Java 程序员 架构 面试 计算机

国庆高质量出行,可视化开启智慧旅游

ThingJS数字孪生引擎

大前端 物联网 可视化 旅游 数字孪生

你应该远离的6个Java特性_Java_张龙_InfoQ精选文章