[雨夜]模拟面试(一)

139 阅读5分钟

“我报名参加金石计划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 构造方法

面试官:

能说下 为什么是这个输出么?都有哪些步骤

我:

image.png 其中 对象是由 头部信息和实例信息组成

头部信息

  1. 对齐填充
  2. 持有指向方法区的指针。
  3. 描述信息(持有当前对象锁的线程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的执行 进行脱敏处理,是为了保护手机号 用户信息等

优势 低耦合 规范统一,损耗低

调研

  1. sharding-jdbc 因为不支持多种加密算法,不支持 Native SQL 函数 自定义类型映射和JDBC等 却需要侵入式的安装,对于老项目不友好
  2. sharding-proxy 它是因为 性能损耗更大 并且需要中心化部署
  3. javaagent 低耦合 规范统一,损耗低

总结

java 基础什么时候 都需要注意。

javaagent 可以学习 并且实践。但是也没必要 感觉这是什么高端技术。。。。

下节写什么呢? 不知道。。。我想想,你也可以评论下。。。。