精华内容
下载资源
问答
  • 动态ip代理的方法有哪些?网络运营中常常需要运用到动态代理IP,在网络营销中占有非常重要的位置。它适用于网络投票,预期目标补量,数据分析等等与互联网息息相关的工作。虽然现在代理IP对于互联网工作者已经不是...

    换动态ip代理的方法有哪些?网络运营中常常需要运用到动态代理IP,在网络营销中占有非常重要的位置。它适用于网络投票,预期目标补量,数据分析等等与互联网息息相关的工作。虽然现在代理IP对于互联网工作者已经不是一个陌生的名词。但是还是又很多人处于知道有这么个东西,却不清楚要怎么使用动态代理IP,也不知道要怎么更换IP。

    一、重启路由器或光猫,因为每一次路由器重启,如果IP是公网的就会发生改变,如果是静态IP,就需要重启光猫才会变动公网IP。这种方法时间久,步骤麻烦,效率低,不适合一些大公司的需求。

    二、用拨号 vps 重拨更换动态IP代理。远程桌面连接后,每次拔号就可以更换一次IP,但是地址是随机的,不过都是在中国的省份,也可以选择单地域拔号VPS,拨出来的是独立一个地域其他IP。这个办法会比重启路由器省时省力,但是一台拔号VPS,只可以运用一个IP。

    三、在浏览器设置动态IP代理。根据浏览器设置动态IP代理,通过变动电脑浏览器更改IP,用于浏览其他的网页。但是对于需要经常更换IP其他消费者而言,还是没有这么方便的。

    四、从代理IP商那里购买代理IP。这个方法是所有方法中最方便快捷,而且IP资源的质量也比较好,还有客服在线答疑解惑。但是现在市面上有很多代理IP商,提供的IP质量也参差不齐。

    展开全文
  • 我们可以从常见的 Java 类来源分析,通常的开发过程是,开发者编写 Java 代码,调用 javac编译成 class 文件,然后通过类加载机制载入 JVM,就成为应用运行时可以使用的 Java 类了。从上面过程得到启发,其中一个...

    我们可以从常见的 Java 类来源分析,通常的开发过程是,开发者编写 Java 代码,调用 javac编译成 class 文件,然后通过类加载机制载入 JVM,就成为应用运行时可以使用的 Java 类了。从上面过程得到启发,其中一个直接的方式是从源码入手,可以利用 Java 程序生成一段源码,然后保存到文件等,下面就只需要解决编译问题了。
    有一种笨办法,直接用 ProcessBuilder 之类启动 javac 进程,并指定上面生成的文件作为输入,进行编译。最后,再利用类加载器,在运行时加载即可。

    对于一个普通的 Java 动态代理,其实现过程可以简化成为:
    提供一个基础的接口,作为被调用类型(com.mycorp.HelloImpl)和代理类之间的统一入
    口,如 com.mycorp.Hello。
    实现InvocationHandler,对代理对象方法的调用,会被分派到其 invoke 方法来真正实现动
    作。通过 Proxy 类,调用其 newProxyInstance 方法,生成一个实现了相应基础接口的代理类实例,可以看下面的方法签名。

    public static Object newProxyInstance(ClassLoader loader,
    Class<?>[] interfaces,
    InvocationHandler h)
    
    展开全文
  • 今天我要问你的问题是,有哪些方法可以在运行时动态生成一个 Java 类? 典型回答 我们可以从常见的 Java 类来源分析,通常的开发过程是,开发者编写 Java 代码,调用 javac 编译成 class 文件,

    在开始今天的学习前,我建议你先复习一下专栏第 6 讲有关动态代理的内容。作为 Java 基础模块中的内容,考虑到不同基础的同学以及一个循序渐进的学习过程,我当时并没有在源码层面介绍动态代理的实现技术,仅进行了相应的技术比较。但是,有了上一讲的类加载的学习基础后,我想是时候该进行深入分析了。

    今天我要问你的问题是,有哪些方法可以在运行时动态生成一个 Java 类?


    典型回答

    我们可以从常见的 Java 类来源分析,通常的开发过程是,开发者编写 Java 代码,调用 javac 编译成 class 文件,然后通过类加载机制载入 JVM,就成为应用运行时可以使用的 Java 类了。

    从上面过程得到启发,其中一个直接的方式是从源码入手,可以利用 Java 程序生成一段源码,然后保存到文件等,下面就只需要解决编译问题了。

    有一种笨办法,直接用 ProcessBuilder 之类启动 javac 进程,并指定上面生成的文件作为输入,进行编译。最后,再利用类加载器,在运行时加载即可。

    前面的方法,本质上还是在当前程序进程之外编译的,那么还有没有不这么 low 的办法呢?

    你可以考虑使用 Java Compiler API,这是 JDK 提供的标准 API,里面提供了与 javac 对等的编译器功能,具体请参考java.compiler相关文档。

    进一步思考,我们一直围绕 Java 源码编译成为 JVM 可以理解的字节码,换句话说,只要是符合 JVM 规范的字节码,不管它是如何生成的,是不是都可以被 JVM 加载呢?我们能不能直接生成相应的字节码,然后交给类加载器去加载呢?

    当然也可以,不过直接去写字节码难度太大,通常我们可以利用 Java 字节码操纵工具和类库来实现,比如在专栏第 6 讲中提到的ASMJavassist、cglib 等。

    考点分析

    虽然曾经被视为黑魔法,但在当前复杂多变的开发环境中,在运行时动态生成逻辑并不是什么罕见的场景。重新审视我们谈到的动态代理,本质上不就是在特定的时机,去修改已有类型实现,或者创建新的类型。

    明白了基本思路后,我还是围绕类加载机制进行展开,面试过程中面试官很可能从技术原理或实践的角度考察:

    • 字节码和类加载到底是怎么无缝进行转换的?发生在整个类加载过程的哪一步?
    • 如何利用字节码操纵技术,实现基本的动态代理逻辑?
    • 除了动态代理,字节码操纵技术还有那些应用场景?

    知识扩展

    首先,我们来理解一下,类从字节码到 Class 对象的转换,在类加载过程中,这一步是通过下面的方法提供的功能,或者 defineClass 的其他本地对等实现。

    protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                       ProtectionDomain protectionDomain)
    protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
                                       ProtectionDomain protectionDomain)

    我这里只选取了最基础的两个典型的 defineClass 实现,Java 重载了几个不同的方法。

    可以看出,只要能够生成出规范的字节码,不管是作为 byte 数组的形式,还是放到 ByteBuffer 里,都可以平滑地完成字节码到 Java 对象的转换过程。

    JDK 提供的 defineClass 方法,最终都是本地代码实现的。 

    static native Class<?> defineClass1(ClassLoader loader, String name, byte[] b, int off, int len,
                                      ProtectionDomain pd, String source);
    
    static native Class<?> defineClass2(ClassLoader loader, String name, java.nio.ByteBuffer b,
                                      int off, int len, ProtectionDomain pd,
                                      String source);

    更进一步,我们来看看 JDK dynamic proxy 的实现代码。你会发现,对应逻辑是实现在 ProxyBuilder 这个静态内部类中,ProxyGenerator 生成字节码,并以 byte 数组的形式保存,然后通过调用 Unsafe 提供的 defineClass 入口。 

    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
          proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
    try {
      Class<?> pc = UNSAFE.defineClass(proxyName, proxyClassFile,
                                       0, proxyClassFile.length,
                                       loader, null);
      reverseProxyCache.sub(pc).putIfAbsent(loader, Boolean.TRUE);
      return pc;
    } catch (ClassFormatError e) {
    // 如果出现ClassFormatError,很可能是输入参数有问题,比如,ProxyGenerator有bug
    }

    前面理顺了二进制的字节码信息到 Class 对象的转换过程,似乎我们还没有分析如何生成自己需要的字节码,接下来一起来看看相关的字节码操纵逻辑。

    JDK 内部动态代理的逻辑,可以参考java.lang.reflect.ProxyGenerator的内部实现。我觉得可以认为这是种另类的字节码操纵技术,其利用了DataOutputStrem提供的能力,配合 hard-coded 的各种 JVM 指令实现方法,生成所需的字节码数组。你可以参考下面的示例代码。 

    private void codeLocalLoadStore(int lvar, int opcode, int opcode_0,
                                  DataOutputStream out)
      throws IOException
    {
      assert lvar >= 0 && lvar <= 0xFFFF;
      // 根据变量数值,以不同格式,dump操作码
        if (lvar <= 3) {
          out.writeByte(opcode_0 + lvar);
      } else if (lvar <= 0xFF) {
          out.writeByte(opcode);
          out.writeByte(lvar & 0xFF);
      } else {
          // 使用宽指令修饰符,如果变量索引不能用无符号byte
          out.writeByte(opc_wide);
          out.writeByte(opcode);
          out.writeShort(lvar & 0xFFFF);
      }
    }

    这种实现方式的好处是没有太多依赖关系,简单实用,但是前提是你需要懂各种JVM 指令,知道怎么处理那些偏移地址等,实际门槛非常高,所以并不适合大多数的普通开发场景。

    幸好,Java 社区专家提供了各种从底层到更高抽象水平的字节码操作类库,我们不需要什么都自己从头做。JDK 内部就集成了 ASM 类库,虽然并未作为公共 API 暴露出来,但是它广泛应用在,如java.lang.instrumentation API 底层实现,或者Lambda Call Site生成的内部逻辑中,这些代码的实现我就不在这里展开了,如果你确实有兴趣或有需要,可以参考类似 LamdaForm 的字节码生成逻辑:java.lang.invoke.InvokerBytecodeGenerator。 

    从相对实用的角度思考一下,实现一个简单的动态代理,都要做什么?如何使用字节码操纵技术,走通这个过程呢?

    对于一个普通的 Java 动态代理,其实现过程可以简化成为:

    • 提供一个基础的接口,作为被调用类型(com.mycorp.HelloImpl)和代理类之间的统一入口,如 com.mycorp.Hello。
    • 实现InvocationHandler,对代理对象方法的调用,会被分派到其 invoke 方法来真正实现动作。
    • 通过 Proxy 类,调用其 newProxyInstance 方法,生成一个实现了相应基础接口的代理类实例,可以看下面的方法签名。
    public static Object newProxyInstance(ClassLoader loader,
                                        Class<?>[] interfaces,
                                        InvocationHandler h)

    我们分析一下,动态代码生成是具体发生在什么阶段呢?

    不错,就是在 newProxyInstance 生成代理类实例的时候。我选取了 JDK 自己采用的 ASM 作为示例,一起来看看用 ASM 实现的简要过程,请参考下面的示例代码片段。

    第一步,生成对应的类,其实和我们去写 Java 代码很类似,只不过改为用 ASM 方法和指定参数,代替了我们书写的源码。 

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    
    cw.visit(V1_8,                      // 指定Java版本
          ACC_PUBLIC,               // 说明是public类型
            "com/mycorp/HelloProxy",  // 指定包和类的名称
          null,                     // 签名,null表示不是泛型
          "java/lang/Object",               // 指定父类
          new String[]{ "com/mycorp/Hello" }); // 指定需要实现的接口

    更进一步,我们可以按照需要为代理对象实例,生成需要的方法和逻辑。

    MethodVisitor mv = cw.visitMethod(
          ACC_PUBLIC,               // 声明公共方法
          "sayHello",               // 方法名称
          "()Ljava/lang/Object;",   // 描述符
          null,                     // 签名,null表示不是泛型
          null);                      // 可能抛出的异常,如果有,则指定字符串数组
    
    mv.visitCode();
    // 省略代码逻辑实现细节
    cw.visitEnd();                      // 结束类字节码生成

    上面的代码虽然有些晦涩,但总体还是能多少理解其用意,不同的 visitX 方法提供了创建类型,创建各种方法等逻辑。ASM API,广泛的使用了Visitor模式,如果你熟悉这个模式,就会知道它所针对的场景是将算法和对象结构解耦,非常适合字节码操纵的场合,因为我们大部分情况都是依赖于特定结构修改或者添加新的方法、变量或者类型等。

    按照前面的分析,字节码操作最后大都应该是生成 byte 数组,ClassWriter 提供了一个简便的方法。 

    cw.toByteArray();

    然后,就可以进入我们熟知的类加载过程了,我就不再赘述了,如果你对 ASM 的具体用法感兴趣,可以参考这个教程。

    最后一个问题,字节码操纵技术,除了动态代理,还可以应用在什么地方?

    这个技术似乎离我们日常开发遥远,但其实已经深入到各个方面,也许很多你现在正在使用的框架、工具就应用该技术,下面是我能想到的几个常见领域。 

    • 各种 Mock 框架
    • ORM 框架
    • IOC 容器
    • 部分 Profiler 工具,或者运行时诊断工具等
    • 生成形式化代码的工具

    甚至可以认为,字节码操纵技术是工具和基础框架必不可少的部分,大大减少了开发者的负担。

    今天我们探讨了更加深入的类加载和字节码操作方面技术。为了理解底层的原理,我选取的例子是比较偏底层的、能力全面的类库,如果实际项目中需要进行基础的字节码操作,可以考虑使用更加高层次视角的类库,例如Byte Buddy等。

    一课一练

    关于今天我们讨论的题目你做到心中有数了吗?试想,假如我们有这样一个需求,需要添加某个功能,例如对某类型资源如网络通信的消耗进行统计,重点要求是,不开启时必须是零开销,而不是低开销,可以利用我们今天谈到的或者相关的技术实现吗?

     


    其他经典回答

    以下来自网友三口先生的回答:

    将资源消耗的这个实例,用动态代理的方式创建这个实例动态代理对象,在动态代理的invoke中添加新的需求。开始使用代理对象,不开启则使用原来的方法,因为动态代理是在运行时创建。所以是零消耗。

    以下来自网友tyson的回答:

    可以考虑用javaagent+字节码处理拦截方法进行统计:对httpclient中的方法进行拦截,增加header或者转发等进行统计。开启和关闭只要增加一个javaagent启动参数就行

     

    展开全文
  • 相对于静态代码分析,Profiling 是通过收集程序运行时的信息来研究程序行为的动态分析方法。其目的在于定位程序需要被优化的部分,从而提高程序的运行速度或是内存使用效率。收集程序运行时信息的方法主要以下三种...

    对于java来说:

    相对于静态代码分析,Profiling 是通过收集程序运行时的信息来研究程序行为的动态分析方法。其目的在于定位程序需要被优化的部分,从而提高程序的运行速度或是内存使用效率。收集程序运行时信息的方法主要有以下三种:

    • 事件方法:对于 Java,可以采用 JVMTI(JVM Tools Interface)API 来捕捉诸如方法调用、类载入、类卸载、进入 / 离开线程等事件,然后基于这些事件进行程序行为的分析。
    • 统计抽样方法(sampling): 该方法每隔一段时间调用系统中断,然后收集当前的调用栈(call stack)信息,记录调用栈中出现的函数及这些函数的调用结构,基于这些信息得到函数的调用关系图及每个函数的 CPU 使用信息。由于调用栈的信息是每隔一段时间来获取的,因此不是非常精确的,但由于该方法对目标程序的干涉比较少,目标程序的运行速度几乎不受影响。
    • 植入附加指令方法(BCI): 该方法在目标程序中插入指令代码,这些指令代码将记录 profiling 所需的信息,包括运行时间、计数器的值等,从而给出一个较为精确的内存使用情况、函数调用关系及函数的 CPU 使用信息。该方法对程序执行速度会有一定的影响,因此给出的程序执行时间有可能不准确。但是该方法在统计程序的运行轨迹方面有一定的优势。
    展开全文
  • 黑盒测试(Black-box Testing,又称为功能测试或...黑盒技术设计测试用例的方法有:等价类划分、边界值分析、因果图分析法等, 等价类划分:是把所有可能的输入数据,即程序的输入域划分成若干部分(子集),然后从
  • 软件测试的方法有哪些

    千次阅读 2012-09-07 16:51:51
    •从测试过程来分:静态分析法、动态测试法; •从观察结构的透明性方式来分:白盒法、黑盒法、灰盒法; •从获得测试数据形式上分:穷尽法;等价类划分法;边界值分析法; •从逻辑分析上分:因果图法;错误推测...
  • 做手游试玩项目IP很重要,IP方案许多种,没有最好,只有最合适。也没有一种方案是可以长期稳定用下去的,需要我们根据最新情况去调整,选择当下最合适的方案,或者多种方案结合使用。下面说下换IP的几种方案,并...
  • 分析JVM动态生成的类

    2019-07-05 13:49:00
    1、生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知; 2、产生的类字节码必须有个一个关联的类加载器对象; 3、生成的类中的方法的代码是怎样的,也得由我们提供。把我们的代码写在一个约定好了接口...
  • Java内存分析3.1 Java内存4、 Class类4.1Class类的常用方法4.2 Class类的获得方式4.3 哪些类型可以Class对象4.4类的加载过程4.5 类的加载与ClassLoader的理解4.6 发生类的初始化4.7、创建运行时类的对象4.8动态...
  • 要从网络测量系统获得最大的动态范围,了解动态范围的本质和哪些方法可用于增加动态范围非常重要。了这些知识,设计人员可以选择合适的方法获得最佳结果,并且把对其他参数的影响降到最小,比如测量速度等。定义...
  • 有哪些祖先?对象可以用哪些方法和属性?自省让处理对象的函数或方法根据传递给函数或方法的对象类型来做决定。即允许对象在运行时动态改变方法成员等属性。 得益于OpenERP ORM 模型的精巧设计,实际上 OpenERP ...
  • 有哪些祖先?对象可以用哪些方法和... 一般来说我们在编程中,对象定义都是预先定义好的。一些 OOP 语言(包括 Python/Java)允许对象是 自省的(也称为 反射)。即,自省对象能够描述自己:实例属
  • ,那就是用大数据去对天气进行分析,从而使得大家能够从容应对雾霾天气。 北京暴雨的事情大家都是知道的,最主要的还是需要气象部门及时、准确地做出预警,并协同其他运营商部门,将这种预警信息第一时间下发到...
  • 数据挖掘是一个动态、强势快速扩展的领域。数据挖掘研究的主要问题,可划分为五组:挖掘方法、用户交互、有效性与可伸缩性、数据类型的多样性、数据挖掘与社会。 一、挖掘方法 目前大牛们已经开发了一些数据挖掘方法...
  • 常见的动态测试方法有:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、路径覆盖和基本路径覆盖。以如图10-8 所示的程序流程图为例,对动态测试技术进行分析。一、语句覆盖语句覆盖是指在测试过程中,设计若干个测试...
  • 您所熟悉的软件测试类型都...采用黑盒技术设计测试用例的方法有:等价类划分、边界值分析、错误推测、因果图和综合策略。  性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标
  • 1. 黑盒测试和白盒测试常用的测试方法有哪些?举例说明。 答:白盒测试:逡辑覆盖法,主要包括诧句覆盖,判断覆盖,条件覆盖,判断条件覆盖,组合条件覆盖、路径覆盖。 黑盒测试:等价划分类,边界值分析,错诨...
  • 交叉引用cross reference是指 这个地址的 数据或代码 引用了哪个地址 以及 被哪些地址的代码所引用。引用了哪个地址,在反汇编就能...这主要是看分析的目的是什么,与运行时动态分析相比各好处,静态分析能得到完整的
  • 目录简述何为动态规划动态规划问题的适用条件动态规划都有哪些类型呢?解题步骤案例实战入门案例简单案例--爬楼梯总结 简述 最近看了一些动态规划的内容,趁着周末,来总结一些,揭一揭这神秘的面纱。 动态规划程序...
  • 聊聊Golang逃逸分析

    2019-09-26 19:31:13
    在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法——分析在程序的哪些地方可以访问到指针。它涉及到指针分析和形状分析。 当一个变量(或对象)在子程序中被分配时,一个指向变量的指针可能逃逸到其它...
  • 关于Java的六大问题分析引导语:Java 编程语言是个简单...本问题讨论变量的初始化,所以先来看一下Java中有哪些种类的变量。1.类的属性,或者叫值域2.方法里的局部变量3.方法的参数 对于第一种变量,Java虚拟机会自...
  • 请设计下你想监控的操作有哪些,用什么方法来监控 想要监控的操作 监控链接了哪些ip和端口 监控注册表信息 监控文件的增删 权限变动 想要用什么方法进行监控 -静态方法 virscan扫描 ip explorer分析属性 ...
  • 算法设计通常有哪些方法至少列出 4种并指出哪些算法具有的某个共有性质 解答 : 算法设计方法有分治算法贪心算法动态规划算法归纳算法回溯算法分支限界 算法等 分治算法贪心算法动态规划算法等算法都具有最优子结构...
  • 二简答题 备忘录方法动态规划算法相比何异同简述之 简述回溯法解题的主要步骤 简述动态规划算法求解的基本要素 简述回溯法的基本思想 简要分析在递归算法中消除递归调用将递归算法转化为非递归算法的方法 简要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 411
精华内容 164
关键字:

动态分析方法有哪些