我觉得相比老的 j2ee, Spring/SpringBoot 已经算轻的了, 虽然离云原生的标准还差了不少, 但是毕竟也是有其他优势的, 就是生态好, 工具 /社区丰富, 也隐藏了一些复杂的底层细节, 所谓"笨重"应该不是首要考虑的问题 此外, Getter/Setter 我觉得是必要的, 如果是真纯数据类型, 已经有 record 类了, 如果要加上一些行为的话, 隐藏在 Getter/Setter 后面是最方便自然的了, 如果只是怕麻烦, 可以用 lombok, 很方便 IService/ServiceImpl 这个应该是如果是接口的话, 底层就会用 JDK 动态代理实现, 如果是有一个 Service 的话, 用的 CGLIB, 据说性能稍微差一点, 反正我的话, 如果接口有多个实现, 就用接口, 如果只是单个实现, 就不要接口 你说一个请求要好几层的话, 这个和接口什么的没有关系, 是设计的问题, 要看你的项目架构怎么设计和定义的了, 一般都得分个请求层 /服务层 /数据层之类的, 如果说 3 层都闲多, 要目你的项目太简单是真不需要, 要么就是还没遇到合在一起遇到的麻烦事. 如果说的是单 Service 层有好几层, 那要看具体情况了, 如果只是单单说是公司规定, 全是模版代码, 我建议如果不能说服老大, 那自己做一个模版代码生成器会方便很多
内存占用和 JIT 、AOT 是没关系的,主要是 Tracing GC 的问题。Tracing GC 就意味着任一时刻内存中必然有一部分数据是“无用”的,造成内存空间的“浪费”。 其他 Tracing GC 的语言也一样,并且 GC 调优有时候还需要用更多的“无用”内存占用换取 GC 更少触发。 其实不用 Tracing GC 也会有其他问题,比如用了对象池 /内存池。在这些情况下,内核看到的内存占用其实都不能代表应用程序的“真实”内存占用,但是这些“没用”的内存又确确实实被占着。
java 的内存问题不单是 tracing gc 带来的占用内存多的问题,还有个更复杂的问题是对象类型的变量是引用,无法嵌套对象。这个不但有内存使用量的开销,还有因为内存布局无法控制可能带来性能损耗。 有些对内存局部性敏感的算法用 java 写出来就是要比 C++ 慢,有时为了优化性能,必须放弃面向对象的写法,把对象数组改成每个属性拆出来单独存数组, 写出来的代码就和 matlab 差不多。 拿 C++ 的话来说,就是 java 的面向对象抽象不是零开销的。