因特马

努力探索B面人生:AI、副业搞钱、人生感悟

因特马

开发中,我们有时候想要修改 jar 中的代码,方便我们调试或者作为生产代码打包上线。但在 IDEA 中,jar 包中的文件都是 read-only(只读模式)。那如何才能修改 jar 包中的源码呢?

  1. 下载 jar 包源码。如果无法获得源码,需要用反编译工具反编译。
  2. 找到 jar 中你想要修改的类,在自己的工程目录下,创建一个同该类一样的包(package)。
  3. 把你要修改的类复制到该包中。此时,可以对该类进行修改。
  4. debug 项目,在该类中打上断点,可以看到代码执行时会进入这个新的类中,说明走的是改后的代码。
  5. 注意,IDEA 会出现 alternative source available for the class 提示。这个是可以随时切换想要执行的同名类。

image-20210429184742586

到这里,调试阶段修改 jar 包中源码的方式就到此为止了。但如果项目想要使用修改后的类打包到生产上运行,还需要继续进行下面的操作。

  1. 接着上面的第 4 步,项目可以正常打包上线。
  2. 如果不想在工程中显示创建一个同名类,想要直接修改 jar 包中的代码的话,可以对新修改的同名类进行编译生成 .class 文件。
  3. 然后将 jar 包解压,找到对应类的 .class 文件,用刚刚编译的新的 .class 文件替换。然后将解压后的 jar 包打成 zip 包。
  4. 最后,将 zip 包后缀修改为 .jar,替换原有工程的 jar 包即可。
阅读全文 »

目前,网上有关宽窄依赖的博客大多都使用下面这张图作为讲解:

Image for post

实际上,这幅图所表达的内容并不完善。其中,窄依赖的内容表达的不够全面,而宽依赖的部分容易让人产生误解。本文,我将用新的绘图带大家搞清楚究竟什么是宽依赖(ShuffleDependency),什么是窄依赖(NarrowDependency)。

为什么会有宽窄依赖?

我们知道,在 Spark 中,数据抽象表示为统一的数据模型 RDD。每一次对 RDD 进行转换(Transformation)操作,我们都会得到一个新的 RDD。例如,rdd2 = rdd1.map(func)。那么,前后的 RDD 自然就形成了某种联系,即新生成的 child RDD 会依赖旧的 parent RDD。而这其中的问题,实际上就是新生成的 RDD 的分区如何依赖 parent RDD 的分区。

阅读全文 »

最近,英雄联盟迎来了 S11 赛季的版本大更新。作为一名从 S2 一路走过来的老玩家,我自然也是非常的关注。除了发生了巨变的装备系统之外,各种各样的 bug,也是在玩家之间炽手可热的话题。这其中,较为严重的一个 bug 之一,就是打野英雄在特定的情况下,可以对野怪一击造成 -2147483648 的伤害。熟悉英雄联盟的玩家应该知道,21 亿在游戏中可以说是一个天文数字。哪怕是血量最多的野怪,在这个伤害面前也会瞬间灰飞烟灭,这简直是有史以来最大的峡谷惨案。

那为什么会出现 -2147483648 这个大的数字呢?或者说,为什么就恰好就是这样一个数字呢?这个数看起来好像并没有什么规律,难道是由于程序异常导致某些数字累加或者累乘造成的?还是游戏开发者留下的一个类似于彩蛋的东西呢?这就是我今天要跟大家分享的内容——从编程的角度来分析这个 21 亿的神秘数字到底是怎么产生的。而这其中所涉及到的计算机知识,都可以作为面试题了!

要想搞清楚这个问题,首先要了解三个概念:二进制、整数类型和补码。

首先说二进制。无论你是否学过计算机,二进制这个词,多多少少你都可能听到过。那什么是二进制呢?首先我们来看下日常生活中我们广泛使用的十进制。十进制由十个数字符号组成,从 0 到 9。在计数过程中,逢十进一。比如说,9 的下一个数就需要进一位变为 10,19 的下一个数需要进一位变为 20,99 的下一个数需要进一位变成 100。同理,二进制就两个数字符号, 0 和 1,计数时逢二进一。比如说,0 就是 0,1 就是 1,十进制的 2 在二进制中就是 10,十进制的 3 在二进制中就是 11,4 则为 100,5 则为 101,以此类推。

阅读全文 »

随着 PyTorch 的不断发展,其生态也越来越繁荣。现如今,安装 PyTorch 是一件非常简单的事情。我们只需要安装 Anaconda,并通过 conda 就可以安装 PyTorch 环境。

目前,网络上大多数 PyTorch 安装教程中有关 CUDA、cuDNN 的安装方法比较混乱且已经过时。本文创作时间为 2020-09-10,接下来我就根据个人实践以及相关资料,整理下如何用正确姿势安装 PyTorch。

安装 Anaconda

下载并安装 Anaconda

Anaconda 是一个基于 Python 的科学计算集成平台,内置了非常全面的数据处理、科学计算等第三方库。其中就包括了我们要安装的 PyTorch。

阅读全文 »

前言

在日常开发中,我们时常需要编写一些重复的、非业务相关的功能性代码。比如实体类私有属性的 get / set 方法、创建日志输出类等。

这也是 Java 饱受诟病的地方之一。往往这些冗余的代码虽然跟业务无关,但由于其功能性又不得不写,十分浪费时间,影响美观不说,后期如果有改动还不方便维护。

为了解决上述痛点,就不得不提到神器 Lombok 了。有了 Lombok,在开发中我们就可以使用简单的注解,来避免编写那些重复的功能性代码。在编译的时候,Lombok 会根据注解自动帮我们生成我们省去的那些代码。是不是很神奇?那么接下来我就来介绍下 Lombok 的常见使用方法。

环境配置

阅读全文 »

前言

在开发中,我们可以通过自定义配置来灵活配置我们的项目。过去,在 SpringMVC 中,我们需要在各种 XML 中定义我们的各项配置,使用起来相对繁琐。而 SpringBoot 为我们提供了更为方便的方式定义配置,只需要在 application.yml 中添加我们需要的配置,然后通过注解读取配置即可。

使用 @Value 读取配置

在类中,我们可以通过给属性打上 @Value 注解,将配置中的参数值绑定到属性上。

application.yml 中,我们添加如下配置。

阅读全文 »

前言

SpringBoot 中的方法调用,默认是单线程顺序执行的。但是在开发中我们可能会存在这样一些场景,例如发送邮件或者记录日志等,这些操作往往比较耗时,但是又不是主业务中跟业务相关的内容。这种场景我们就可以选择使用 @Async 异步方法执行,即用其它线程来异步执行某些耗时操作,从而节省主线程的运行等待时间。

使用 @Async 异步执行方法

想要使方法异步执行非常简单,简单来说,只需要在需要异步执行的方法上添加 @Async 注解即可。

编写一个 @Service 服务类,模拟耗时操作。在方法的前后,我们打上开始和结束日志,并输出线程名。

阅读全文 »

前言

在开发中,我们会有定时执行某些任务的需求,例如定时清理过期文件、定时发送邮件等等。SpringBoot 为我们提供了便捷的方式来配置定时任务,只需要打上几个注解即可。那么下面让我们来看看 SpringBoot 中如何开发定时任务。

开启定时任务

想要使用定时任务,需先打开定时任务开关。
在入口类中添加 @EnableScheduling 注解

1
2
3
4
5
6
7
@SpringBootApplication
@EnableScheduling
public class SchedulerTaskApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulerTaskApplication.class, args);
}
}
阅读全文 »

前言

在之前的章节,我们已经用到了 Controller 的部分功能——外界通过 HTTP 请求,访问 SpringBoot 中的方法。这就是我们熟知的 Web 接口,是客户端与后端应用交互的重要方式之一。

那么在本章,我们就来整理下如何使用 @Controller 实现 RESTful Web 接口。

@Controller 的使用

基本介绍

阅读全文 »

前言

作为 Java 后端开发,我们免不了要和数据库打交道。那么我们如何在 SpringBoot 中优雅地与数据库交互呢?

目前,主流的方式是使用 JPA 或者 MyBatis 作为访问数据库的框架。JPA 的前身是 Hibernate,其宣传的亮点是不需要写 SQL 就能实现数据的交互。对于简单的单表查询来说,JPA 有其优势,可以使开发效率大大提高。但是对于复杂的多表关联查询场景,MyBatis 灵活的优势就凸显出来了。

我在一开始用 SpringBoot 访问数据库的时候,用的就是 MyBatis,所以对 MyBatis 的使用相对熟悉一些。而自工作以来,见到的项目大部分都是 SSM 架构的。所以本章就针对 MyBatis 介绍它与 SpringBoot 如何进行整合。

配置工程环境

阅读全文 »
0%