“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第n篇文章,点击查看活动详情”
序
昨天做 组件的压测,涉及到了内存优化 写一篇整理下 走起
说实话 写文档 花的时间是真多
根据本文 还有疑问的点
面试官:
“请说下 下面的输出结果 ”
package com.example.demo.test;
public class Father {
private int age;
private String name;
static {
System.out.println("Father static 代码块");
}
{
System.out.println("Father 代码块");
}
public Father() {
System.out.println("Father 构造方法");
}
}
package com.example.demo.test;
public class Son extends Father{
private static String staticStr = "asdas";
private int age;
private String name;
static {
System.out.println("Son static 代码块");
}
{
System.out.println("Son 代码块");
}
public Son() {
System.out.println("Son 构造方法");
}
public static void main(String[] args) {
new Son();
}
}
我:
输出为
Father static 代码块
Son static 代码块
Father 代码块
Father 构造方法
Son 代码块
Son 构造方法
面试官:
“能说下 为什么是这个输出么?都有哪些步骤 ”
我:
其中 对象是由 头部信息和实例信息组成
头部信息
- 对齐填充
- 持有指向方法区的指针。
- 描述信息(持有当前对象锁的线程id 和 持有对象锁的线程个数,在gc中存活的生命周期数,偏向锁的标识)
面试官:
“嗯嗯,这个理论谁都会,那你感觉这个对你的工作中有用么? 有什么用? ”
我:
“其实懂点原理 也就是八股文还是有点作用的,因为前面前辈写的东西 我们只能先学 先模仿才有可能创新。。。都不懂 创新个锤子。。。我感觉类加载器 和 class加密 比较有用 ”
面试官:
“可以细说下么?有什么应用 ”
我:
“类加载器 那块 第一印象是 为了安全,会从根上找, ”
双亲委派机制 上述加载器的加载顺序是:首先加载自定义加载器,然后是应用程序类加载器,然后再是扩展类加载器,最后才是引导类加载器
加载的方式:
自定义加载器加载 加载到类 则返回
没有找到,向上委托(父加载器,没有继承关系)
appClassLoad(应用程序加载器) 加载到类 返回
没有找到,委托上级
extClassLoad(扩展类加载器) 加载到类 返回
没有找到,委托上级
classLoad(引导类) 加载到类 向下委托
没有找到,再向下委托 。。。。
为啥不从system(引导类) 开始往下找,还要来回循环一遍?
基本上大部分的类加载的都是我们自己写的内容(自带的内容需要加载的很少),双亲委派机制只有第一次会从app开始加载,第二次的时候不用再向上委托了,如果从system开始往下找,那么循环会更多次。
还有两个特别重要的原因(主要原因)
1. 沙箱安全机制,避免核心api库被篡改
比如我也定义个String,如果从上往下,那么String不是被覆盖了?
2. 避免类的重复加载
如何打破双亲委派机制?
其实很简单,就不往上委托,自己去加载
重写我们的 loadClass方法就可以了,但是要注意核心的比如Object这种类不能自定义
加载(会有沙箱安全问题)
java默认是双亲委派机制,为什么要打破?
最常见的打破双亲委派机制就是我们的Tomcat
原因:
1.tomcat 是一个容器,同时会部署多个应用,如果我们多个应用程序用的东西都是不同版本的,一个jdk6 一个jdk8 那么不是就出问题了?所以要保证相互隔离
2.相同的类库相同的版本最好能共享,不然有10个就需要10个相同类库加载
3.基于安全考虑,应用程序的类库和web容器类库要隔离开来
class 加密那个
之前是因为 反编译工具能看源代码,刚实习的时候 因为做私活,然后不想让客户直接反编译代码 能copy走,所以想做一个 加密工具,,,虽然当时就有加密工具,但是奈何 我当时一个月2k。。。不舍得花钱
当时我就是 加密 Class 文件中每个方法的 Java 字节码,运行时在 Java agent 中动态解密
简单来说 就是 得到一个加密的jar 和 agent.jar 然后放到同一个目录,执行的时候 脚本里写
java -javaagent:agent.jar -jar xxx.jar
后来因为 同一个系统 给多个用户,搭建多个环境,他们的密码都是不一样的,就做了一个远程的 获取密码。
后来又因为 它可以拦截我的远程请求,对请求 和 请求/返回参数加密 来动态控制 加密和使用权限
agent 这个我听过 但是用的少,还有什么地方使用么?
为了让业务放最低限度的接入,会选择 java-agent 通过这种字节码插桩的方式 动态对接口的访问 进行处理。。
之前公司是 用agent 对 接口 和 sql的执行 进行脱敏处理,是为了保护手机号 用户信息等
优势 低耦合 规范统一,损耗低
调研
- sharding-jdbc 因为不支持多种加密算法,不支持 Native SQL 函数 自定义类型映射和JDBC等 却需要侵入式的安装,对于老项目不友好
- sharding-proxy 它是因为 性能损耗更大 并且需要中心化部署
- javaagent 低耦合 规范统一,损耗低
总结
java 基础什么时候 都需要注意。
javaagent 可以学习 并且实践。但是也没必要 感觉这是什么高端技术。。。。
下节写什么呢? 不知道。。。我想想,你也可以评论下。。。。