首页 文章 精选 留言 我的

精选列表

搜索[增量式],共10000篇文章
优秀的个人博客,低调大师

OpenCTI —— 开放式网络威胁情报平台

OpenCTI 即 Open Cyber Threat Intelligence Platform,开放网络威胁情报平台。它的创建是为了构建、存储、组织和可视化有关网络威胁的技术和非技术信息。 它使用基于 STIX2 标准的知识模式来执行数据的结构化。并被设计为现代 Web 应用程序,包括 GraphQL API 和面向 UX 的前端。此外,OpenCTI 可以与其他工具和应用程序集成,如 MISP、TheHive、MITRE ATT 和 CK 等。 OpenCTI 的目标是创建一个综合工具,允许用户利用技术(如 TTP 和可观测量)和非技术信息,同时将每条信息链接到其主要来源(报告、MISP 事件等),并具有每个信息之间的链接、首次和最后看到的日期、置信水平等功能。该工具能够使用MITRE ATT 和 CK 框架(通过专用连接器)来帮助构建数据。用户还可以选择实现自己的数据集。 一旦数据被利用和处理,就可以从现有关系中推断出新的关系,以便于理解和表示这些信息。这允许用户从原始数据中提取和利用有意义的信息。 OpenCTI 不仅允许导入,还允许以不同格式(CSV、STIX2 捆绑包等)导出数据。目前正在开发连接器以加速工具与其他平台之间的交互。 安装 使用 Docker(推荐) 手动安装

优秀的个人博客,低调大师

Java函数式编程-3.流(Stream)

List<String> words = Arrays.asList("hello","world"); List<String> chars = words.stream() .flatMap(word -> Stream.of(word.split(""))) .collect(Collectors.toList()); Jdk8中新增的特性旨在帮助程序员写出更好的代码,其中对核心类库的改进是很关键的一部分。对核心类库的改进主要包括集合类的API和新引入的流(Stream)。流使程序员得以站在更高的抽象层次上对集合进行操作。 1.什么是流(Stream)? Stream是特定类型的对象形成的一个队列并支持聚合操作。 Java中的Stream并不会存储元素,而是按需计算。流的来源可以是集合,数组,I/O channel, 产生器generator 等。聚合操作类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。和以前的Collection操作不同, Stream操作还有两个基础的特征:Pipelining中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道,如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。 在 Java 8 中, 集合接口有两个方法来生成流: stream() − 为集合创建串行流。 parallelStream() − 为集合创建并行流。 List<String> list = Arrays.asList("a", "b", "c", "d", null); List<String> filtered = list.stream().filter(e -> Objects.nonNull(e)).collect(Collectors.toList()); long count = list.parallelStream().filter(e -> Objects.nonNull(e)).count(); 2.内部迭代 Java程序员在使用集合时,一个通用的模式时在集合上进行迭代,在迭代过程中处理每一个元素并返回处理结果。通常代码时这样的: List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); int sum = 0; Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { sum += iterator.next(); } System.out.println(sum); 这段代码本身没什么问题就写起来有点麻烦,就其背后原理来看其实就是一个封装了迭代的语法糖,首先调用iterator方法产生一个新的Iterator对象进而控制整个迭代过程,这就是外部迭代。 然而外部迭代的问题在于首先,很难抽象出后续提到的复杂操作,另外从本质上来讲只是一种串行化操作。总体来看使用for循环会将行为和方法混为一谈。另一种方法是内部迭代,和调用iterator()作用一样使用stream()方法,该方法不是返回一个控制迭代的Iterator对象,而是返回内部迭代中的相应接口:Stream。示例如下: List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Integer sum = list.stream().filter(e -> e > 5).reduce(0, Integer::sum); System.out.println(sum); 3.实现机制 通常在Java 中调用一个方法计算机会随即执行操作:比如,System.out.println("hello world!")会在终端上输出一条信息。Stream里的一些方法略有不同,它们虽是普通Java方法但是返回的Stream对象并不是一个新的集合,而是创建新集合的配方。 list.stream().filter(e -> e > 5); 上述代码并未做什么实际性的工作,filter只是刻画出了Stream但是并没有产生新的集合,像filter这样只描述Stream,最终不产生新集合的方法惰性求值方法,而像sum()这样最终从Stream产出值的方法叫做及早求值方法。如果在filter方法中添加一条输出语句就会比较清楚的看出差异。 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); list.stream().filter(e -> { System.out.println(e); return e > 5; }); 如果将上述语句添加一个及早求值方法就可以看到集合中的元素被打印出来。 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); list.stream().filter(e -> { System.out.println(e); return e > 5; }).findFirst(); 判断一个操作是惰性求值还是及早求值很简单,只要返回值是Stream那么是惰性求值。使用这些操作的理想方式就是形成一个惰性求值链,最后用一个及早求值的操作返回想要的结果,这正是他的合理之处。那为什么要区分惰性求值和及早求值呢?原因很简单只需要一次迭代就可以得到全部结果,例如 :上述代码只需要找到第一个大于5的数而不需要比较所有集合元素。 4.常用的流操作 为了更好的学习Stream,我们接下来学习一些常用的stream操作。 filter 如果需要在遍历集合元素时清洗非法元素可以使用filter方法,我们在上述讨论过程中已经使用过该方法。filter接收一个函数作为参数,该函数使用lambda表达式表示,如果被清洗元素符合预期则返回true,其实看源码会发现这个lambda表达式是我们之前讲过的 Predicate<T>函数。 collect 这个方法是由Stream生成一个List,是一个及早求值操作。Jdk8中借鉴了很多Scala的设计思想,Stream的of方法可以用来生成一个新的Stream,我们来看下边的一个例子。 List<String> list = Stream.of("a", "b", "c","d","e").collect(Collectors.toList()); map map函数是用来讲一个类型转换为另外一种类型,参数同样是一个lambda表达式对应我们之前讲过的Function<T, R> 函数。因为map是一个惰性求值方法我们配合之前的collect看一个例子。 List<String> list = Stream.of("a", "b", "c").map(e -> e.toUpperCase()).collect(Collectors.toList()); System.out.println(list); flatMap 和map类似,不同的是其每个元素转换得到的是Stream对象,最终会把转换得到的多个Stream连接成一个Stream。 List<String> words = Arrays.asList("hello","world"); List<String> chars = words.stream() .flatMap(word -> Stream.of(word.split(""))) .collect(Collectors.toList()); 上述代码我们可以得到输出结果 :[h, e, l, l, o, w, o, r, l, d],如果将flatMap换成map会发现我们得到了一个List<Stream<String>> ,大家感兴趣可以上手一试。 max和min 和之前讲的函数不同,这两个方法要求参数是一个比较器Comparator<T> Integer min = Stream.of(1,2,3,4,5).min(Integer::compare).get(); System.out.println(min); Integer max = Stream.of(1,2,3,4,5).max(Integer::compare).get(); System.out.println(max); reduce 该函数可以实现从一组值中生成一个值,在上述例子中用到的 sum、max、min本质上都是reduce操作。Stream的求和结果每一步都将Stream中的元素累加至accumulator,遍历至Stream中的最后一个元素时,accumulator的值就是所有元素的和。我们看如下例子 Integer sum = Stream.of(1, 2, 3, 4, 5).reduce(0, (acc, e) -> acc + e); System.out.println(sum); 这段代码如果你对scala熟悉那么会很容易理解,acc作为累加器存储了中间计算结果,整个lambda函数本质上是我们之前讲过的BinaryOperator。

优秀的个人博客,低调大师

Android解耦式so库加载方案

背景说明 在业务开发过程中经常会进入一些三方sdk,这些三方的sdk引入so库,有些so库文件还比较大,这时候我们就需要考虑so库从网络获取异步加载,减少发布包的体积 传统方案 关于so异步加载方案,网上的资料随便搜下大把,核心思想 so库文件放到网络->下载到本地沙盒->通过System.load载入 看起来挺简单的 然而挺多资料没提到的是 so库存在依赖关系 比如当你把libunity.so下载下来通过 System.load("/data/data/com.example.soload/files/libunity.so") 加载的时候会得到如下异常 java.lang.UnsatisfiedLinkError: dlopen failed: library “libmain.so” not found at java.lang.Runtime.loadLibrary0(Runtime.java:1071) at java.lang.Runtime.loadLibrary0(Runtime.java:1007) at java.lang.System.loadLibrary(System.java:1667) 原因分析 解决方案 载入libunity.so之前需要先载入libmain.so 扩展思考 我们写代码的时候怎么控制加载顺序呢 https://github.com/facebook/S... https://github.com/KeepSafe/R... 以上2个开源库 都有处理相关逻辑 核心思想就是解析so库ELF格式,分析依赖并递归,直到依赖库都加载完成再载入自身 这里不扩展开来 有兴趣的伙伴可以看源码研究下 text relocations问题 当你把liblbs.so下载下来通过 System.load("/data/data/com.example.soload/files/liblbs.so")的时候又出现意外了 java.lang.UnsatisfiedLinkError: dlopen failed: “/data/data/com.example.soload/files/liblbs.so” has text relocations ( https://android.googlesource.... at java.lang.Runtime.load0(Runtime.java:938) at java.lang.System.load(System.java:1631)== 原因分析: https://blog.csdn.net/chjqxxx... 扩展思考: 我们可以通过命令进行自查 有源码的可以重新编译,没有源码的只能通过降低targetSdkVersion处理(然而也是治标不治本) 进阶方案 除了System.load方案 还有没有其他方案呢 答案当然是肯定的 https://github.com/Tencent/ti... 核心思路:通过反射把自定义的native库path插入nativeLibraryDirect ories最前面,即使安装包libs目录里面有同名的so,也优先加载指定路径的外部so 这里截取tinker部分代码 com.tencent.tinker.lib.library.TinkerLoadLibrary.java 这个方案是不是看起来更简单了,由于这个方案是非常规手段,存在兼容风险, 我们需要验证该方案的兼容性,写个helloword的so,通过该方案加载,提前找个版本线上带上去,进行埋点统计 截至目前最新版上线2天 统计到数据如下 其中失败的1例是上线前自测故意让校验失败产生的 也就是说截至目前可以认为改方案是靠谱的 当然了如果后续有新的Android系统版本更新 我们还需要关注新版本的兼容情况 项目应用 上面铺垫了那么多,现在进入正题 技术方案是一回事,落实到实际项目是另一回事 现在开始我们思考下如下几个问题 项目中引用的so库都是那些功能再用何时载入 三方jar(aar)引入的so库加载时机不受我们代码逻辑控制 使用的so库那些适合做异步加载 so库文件没有下载完成之前 用户用相关功能如何处理 版本迭代so文件升级如何处理 打包阶段如何把so文件进行剔除 解决问题1、2、3 我们可以通过切面编程的思路解决,这里用到了开源库https://github.com/HujiangTec... 由于so库的加载都是通过调用系统函数System.loadLibrary进行, 那么我们全局拦截该函数的调用并打印调用链, 运行app,配合日志,就能分析so库的具体使用情况 这里我们需要根据自己业务场景分析,比如app进入到首页依赖的库不建议进行异步加载,需要异步加载的库最好是完成一个功能(我们需要按照经验进行逻辑分组 参考文章开头的图) 解决问题4、5 Android是依据Activity作为活动单位,启动Activity是通过startActivity函数调用进行的,那么我们就可以拦截织入自己的逻辑 大致思路如下 对应实现部分代码截图 通过规则配置化+字节码拦截的逻辑 对原有业务无侵入即可实现动态加载 研发关注正常的业务逻辑 不需要针对性编写代码 后续引入新的so库,修改配置文件即可 在实现的过程中有些细节是需要考虑的 比如校验下载文件的完整性,下载要不要支持断点续传,so文件需要更新如何处理等 解决问题6 通过上面的介绍,我们实现了so文件的异步加载 但是打包的时候 我们如何剔除so 减少最终发布包的大小 可以在build.gradle进行配置 但是上面提到了我们是通过json配置的规则 这样再重复配置一遍 而且还有可能2处配置不一致 而且我们的大原则是解耦 那么我们就继续hook打包流程 汇总小结 通过上面的介绍大致说明了原理 有兴趣的伙伴可以评论区留言,提出自己的想法 目前还在灰度验证阶段,等线上验证稳定后在评论区放出相关代码 so异步加载方案大同小异,该方案跟其他方案相比 个人感觉特色就是侵入性低 接入只需要3个步骤 未完待续 目前该方案还存在几个点有待优化 ==================== 问题1 目前用的是进阶方案实现的so库加载 比较理想的方式是传统方案和进阶方案都应该支持 一开始其实我想用传统方案去实现 但是该方案在unity那块有问题(unity相关so的加载逻辑有点特殊 存在通过jni直接加载so的情况 由于没有源码 内部逻辑不太清楚 ) 后续还需要研究完善 毕竟官方System.load是官方提供的api 更可靠 问题2 进度加载的dialog是依附于调用startActivity的窗口 如果startActivuty之后里面 立马调用finish会导致dialog泄露 这个是需要注意的一个点 也就意味着对原有逻辑存在一定依赖 这个可以通过启动一个FLAG_ACTIVITY_NEW_TASK类型的activity 代理解决 但是感觉这样有点重 目前还有点纠结 问题3 目前文件只是放到了阿里云,用户的网络环境复杂多变,需要考虑支持腾讯云,七牛云等更多的服务商。 问题4 上传到oss的动作目前是动手完成的,需要做成脚本。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册