几周前,我们新开了一系列文章,旨在深入 JavaScript,探寻其工作原理。我们认为通过了解 JavaScript 的构建方式和其运行规则,我们能写出更好的代码和应用。
第一篇文章重点介绍了引擎、运行时和调用栈的概述。第二篇文章仔细地分析了 Google's V8 JavaScript 引擎的内部部分并且为如何编写更好的 JavaScript 代码提供了一些建议。
这是第三篇文章,我们将会讨论一个由于日常使用的编程语言日益成熟和复杂度提升从而让开发者忽略的话题——内存管理。我们还将提供一些有关如何处理 SessionStack 中 JavaScript 内存泄漏的建议,因为我们需要确保 SessionStack 不会导致内存泄漏,也不会增加我们集成的 Web 应用程序的内存消耗。
概述
像 C 语言,拥有底层原始的内存管理方法,例如:malloc() 和 free()。这些原始的方法被开发者用来从操作系统中分配内存和释放内存。
然而,JavaScript 在创建诸如对象等(objects,strings,etc)变量时会分配内存,并且当它们不再被使用的时候会“自动”释放它们,这个过程被称为垃圾回收。
释放资源的这种看似“自动”的性质是造成困扰的根源。它给 JavaScript (和其它高级语言)开发者一个错误的印象——他们可以选择不关心内存管理。这是一个很大的错误。
即使是使用高级语言,开发者对内存管理也应该有所了解(至少要有基础的了解)。有时,开发者必须理解自动内存管理会遇到问题(例如:垃圾回收中的错误或者性能问题等),以便能够正确处理它们。(或者是找到适当的解决方法,用最小的代价去解决。)
内存的生命周期
无论你使用那种语言,内存的生命周期基本是都差不多:
以下是生命周期中每一步发生了什么的一个概述:
Allocate memory —— 操作系统分配内存,允许你的程序使用它。在基础语言中(例如 C ),这是一个开发者自己处理的明确操作。然而,在高级语言中,它已经为你处理了。
Use memory —— 现在你就可以使用之前分配好的内存了。当你在代码中使用变量时,读 和 写 的操作正在发生。
Release memory —— 现在该释放你不再需要的内存了,以便它们能够被再次使用。与分配内存的操作一样,这种操作在基础语言中是明确执行的。
要快速了解调用栈和内存堆的概念,你可以阅读我们该主题的第一篇文章。
什么是内存
在直接讨论 JavaScript 中的内存之前,我们先简略地讨论下一般内存是什么以及它的工作原理。
在硬件层面,计算机内存是有大量触发电路组成的。每个触发电路包含了一些晶体管并且能够存储一个位(bit)。单个触发器可通过唯一的标识符寻址,因此我们可以读取并重写它们。因此,在概念上,我们可以将整个计算机内存看作是我们可以读和写的一个由位组成的大数组。
因为作为人类,我们不是很善于在 位 上进行思考和计算,所以,我们将位组成更大的组,它们可以一起用来表示数字。8位称为1字节(byte)。除了字节之外,还有字(有时是 16 位,有时是 32 位)。
很多东西都存储在内存中:
所有程序使用的所有变量和其他数据。
程序的代码,包括操作系统的。
编译器和操作系统共同合作,帮助你管理内存,但我们建议你查看一下引擎盖下的内容。
编译代码时,编译器可以检查原始数据类型,并提前计算出需要多少内存。然后将所需的数量分配给调用堆栈中的程序。这些变量分配的空间称为堆栈空间,因为随着函数被调用,它们的内存被添加到现有存储器的顶部。当它们终止时,它们以 LIFO (last-in,first-out)顺序被移除。例如,考虑以下声明:
int n; // 4 bytes
int x[4]; // array of 4 elements, each 4 bytes
double m; // 8 bytes
编译器立即会看到这段代码需要: 4 + 4x4 + 8 = 28 bytes。
这是现在整数和双精度的工作原理。大约 20 年前,整数通常为 2 字节,双精度为 4 字节。你的代码应该永远不依赖于此时基本数据类型的大小。
编译器将插入与操作系统交互的代码,以便在堆栈中请求要存储的变量所需的字节数。
在上面的示例中,编译器知道每个变量的精确内存地址。事实上,每当我们写入变量 n 时,在系统内部都会被翻译为“内存地址 4127963” 这样的东西。
注意,如果我们这里尝试访问 x[4] ,我们可能会访问到和 m 相关联的数据。这是因为我们访问的元素在数组中并不存在——这 4 个字节比数组中最后一个元素 x[3] 还要远,可能会读取(或重写) m 的位。这肯定会对程序产生难以理解的不良影响。
当函数调用其他函数时,每个函数在调用时都会获得自己的堆栈块。它保存所有的局部变量,还有一个程序计数器,可以记住函数在执行中的位置。当函数执行完成时,其内存块可以再次用于其他目的。
动态分配
不幸的是,当我们在编译一个不知道多少内存的变量时,事情就变的不那么容易了。假设我们要做如下的事情:
int n = readInput(); // reads input from the user
...
// create an array with "n" elements
这样,在编译的时候,编译器不知道数组需要多少内存,因为它依靠用户提供的输入。
因此,它不能为堆栈上的变量分配空间。相反,我们的程序需要在运行时明确地要求操作系统获得适当的空间量。这个内存时从堆空间分配的。静态和动态内存分配的区别如下表所示:
Static allocation
Dynamic allocation
编译时内存大小确定
编译时内存大小不确定
编译阶段执行
运行时执行
分配给栈
分配给堆
FILO
没有特定的顺序
为了充分了解动态内存分配的工作原理,我们需要花更多的时间在指针上,这可能与这篇文章的主题有些偏离了。如果你有兴趣了解的话,可以在评论中通知我们,我们可以在未来的文章中详细介绍指针。
JavaScript 中的分配
现在,我们将要解释 JavaScript 中第一步(分配内存)是如何工作的。
JavaScript 解放了开发者处理内存分配的责任——JavaScript 自己在声明 values 时就做了这件事。
var n = 374; // allocates memory for a number
var s = 'sessionstack'; // allocates memory for a string
var o = {
a: 1,
b: null
}; // allocates memory for an object and its contained values
var a = [1, null, 'str']; // (like object) allocates memory for the
// array and its contained values
function f(a) {
return a + 3;
} // allocates a function (which is a callable object)
// function expressions also allocate an object
someElement.addEventListener('click', function() {
someElement.style.backgroundColor = 'blue';
}, false);
一些函数调用也会导致对象分配:
var d = new Date(); // allocates a Date object
var e = document.createElement('div'); // allocates a DOM element
方法可以分配新值或对象:
var s1 = 'sessionstack';
var s2 = s1.substr(0, 3); // s2 is a new string
// Since strings are immutable,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.
var a1 = ['str1', 'str2'];
var a2 = ['str3', 'str4'];
var a3 = a1.concat(a2);
// new array with 4 elements being
// the concatenation of a1 and a2 elements
JavaScript 中使用内存
基本上在 JavaScript 中使用内存的意思就是在内存在进行 读 和 写 。
这个操作可能是一个变量值的读取或写入,一个对象属性的读取或写入,甚至是向函数中传递参数。
当内存不再需要时释放它
大多数的内存管理问题发生在这个阶段。
这里最困难的任务就是确定内存何时就不再被需要了。它通常需要开发人员确定程序中哪里不再需要这样的内存,并释放它。
高级语言拥有垃圾回收器,它的职责就是追踪内存分配和使用情况,找到不再被使用的内存,然后自动地释放它。
不幸的是,这个过程只能得到一个近视的值,因为内存是否被需要是不可判定的(不能用算法求解)。
大多数垃圾回收器通过判断内存是否能够被再次访问来工作的,例如:指向它的所有变量都超出了作用域。然而,这只能得到一个近似值。因为在任何位置,存储器位置可能仍然具有指向其范围的变量,但是它可能将永远不会被再次访问了。
垃圾回收
由于事实上发现内存“不再被需要”是不可判定的,因此垃圾收集的通常解决方案都存在局限性。本节将介绍理解主要垃圾收集算法及其局限性的必要概念。
内存引用
垃圾回收算法依靠的主要概念就是引用 。
在内存管理的上下文中,如果前者具有对后者的访问权限(可以是隐式的或者显式的),则一个对象成为了另一个对象的引用。例如:JavaScript 对象具有对其原型(隐式引用)及其属性值(显式引用)的引用。
在上下文中,“对象”的定义扩展到比常规 JavaScript 对象更广泛的东西,并且还包含了函数的作用域(或者全局的词法作用域)。
词法作用域定义了如何在嵌套函数中解析变量名称:即使父函数已返回,内部函数也可以包含父函数的范围。
引用计数——垃圾回收
这是最简单的垃圾回收算法。如果一个对象指向它的引用数为 0,那么它就应该被“垃圾回收”了。
看一下下面的代码:
var o1 = {
o2: {
x: 1
}
};
// 2 objects are created.
// 'o2' is referenced by 'o1' object as one of its properties.
// None can be garbage-collected
var o3 = o1; // the 'o3' variable is the second thing that
// has a reference to the object pointed by 'o1'.
o1 = 1; // now, the object that was originally in 'o1' has a
// single reference, embodied by the 'o3' variable
var o4 = o3.o2; // reference to 'o2' property of the object.
// This object has now 2 references: one as
// a property.
// The other as the 'o4' variable
o3 = '374'; // The object that was originally in 'o1' has now zero
// references to it.
// It can be garbage-collected.
// However, what was its 'o2' property is still
// referenced by the 'o4' variable, so it cannot be
// freed.
o4 = null; // what was the 'o2' property of the object originally in
// 'o1' has zero references to it.
// It can be garbage collected.
循环依赖造成的问题
出现循环依赖就会产生限制。在以下的示例中,将创建两个对象并引用彼此,从而创建了一个循环。在函数调用之后,它们离开了作用域,因此它们实际上已经无用了,可以被释放了。然而,引用计数算法认为,由于两个对象中的每一个至少被引用了一次,所以也不能被垃圾回收。
function f() {
var o1 = {};
var o2 = {};
o1.p = o2; // o1 references o2
o2.p = o1; // o2 references o1. This creates a cycle.
}
f();
标记扫描算法
为了确定一个对象是否被需要,这个算法会确定对象是否可以访问。
该算法由以下步骤组成:
垃圾回收器构建“roots”列表。Roots 通常是代码中保留引用的全局变量。在 JavaScript 中,“window” 对象可以作为 root 全局变量示例。
所有的 roots 被检查并标记为 active(即不是垃圾)。所有的 children 也被递归检查。从 root 能够到达的一切都不被认为是垃圾。
最终,垃圾回收期会将所有没有被标记为active的内存回收,释放到系统。
这个算法优于前一个,因为“一个对象零引用”会让这个对象不是可达的。反过来就不一定对了,因为存在循环引用。
截至 2012 年,所有现代浏览器都配备了 mark-and-sweep 机制的垃圾回收器。过去几年,JavaScript 垃圾回收(代数、增量、并行、并行垃圾收集)领域的所有改进都是对该算法(mark-and-sweep)的实现进行改进,但并没有对垃圾回收算法本身进行改进,其目标是确定一个对象是否可达。
在本文中,你可以阅读到更多关于垃圾回收的详细信息,当然也包含对其的优化。
循环引用不再是问题
在上面的第一个例子中,在函数调用后,两个对象不再被从全局对象可访问的东西所引用。因此,垃圾回收器将发现它们是不可达的。
尽管两个对象还是存在引用,但是他们从 root 出发已经是不可达的了。
反垃圾收集器的直接行为
虽然垃圾收集器很方便,但他们也有自己的一系列决策。其中一个是非确定论。换句话说,GCs 是不可预测的。你不能真正的知道回收是什么时候执行的。这意味着在某些情况下,程序使用的内存要比实际需要的还多。在另外一些情况下,如果程序特别敏感,那么一些短暂的暂停会显得特别明显。虽然不确定性意味着回收执行的时间不能被确定,但是大多数 GCs 的实现是共享模式——在分配内存期间执行回收遍历。如果没有分配执行,大多数 GCs 保持空闲状态。考虑一下情况:
相当大的一组分配被执行。
大多数元素(或全部)被标记为不可达(可以认为这些内存我们不再需要)。
没有更进一步的内存分配行为。
在这种情况下,大多数 GC 将不会再运行任何进一步的收集。换句话说,即使有不可达的引用变量可以被收集,但是它们并没有被收集器声明。这虽然不是严格的内存泄漏,但仍然会导致使用内存比通常的内存要高。
什么是内存泄漏
实质上,内存泄漏可以被定义为应用程序不再需要的内存,但由于某种原因,内存不会返回到操作系统或可用内存池中。
编程语言支持多种管理内存的方法。然而,某块内存是否被使用实际上是一个不确定的问题。换句话说,只有开发人员可以清楚一块内存是否可以释放到操作系统又或者不该被释放。
某些编程语言提供了一些特性,帮助开发者处理这些事情。另外一些语言期望开发者能够完全自己去明确地控制内存。维基百科有关于手动和自动内存管理的好文章。
四种常见的 JavaScript 内存泄漏
1:Global variables
JavaScript 以有趣的方式处理未声明的变量:对未声明的变量的引用在全局对象内创建一个新变量。在浏览器中,全局对象就是 window。换种说法:
function foo(arg) {
bar = "some text";
}
等价于:
function foo(arg) {
window.bar = "some text";
}
如果 bar 被假定为仅仅在函数 foo 的作用域范围内持有对变量的引用,但是你却忘记了使用 var 来声明它,那么就会创建一个意外的全局变量。
在这个例子中,泄漏一个简单的字符串不会有太大的伤害,但肯定会变得更糟的。
可以通过另一种方式创建意外的全局变量:
function foo() {
this.var1 = "potential accidental global";
}
// Foo called on its own, this points to the global object (window)
// rather than being undefined.
foo();
为了防止这些错误的发生,可以在 JavaScript 文件开头添加 “use strict”,使用严格模式。这样在严格模式下解析 JavaScript 可以防止意外的全局变量。
即使我们讨论了如何预防意外全局变量的产生,但是仍然会有很多代码用显示的方式去使用全局变量。这些全局变量是无法进行垃圾回收的(除非将它们赋值为 null 或重新进行分配)。特别是用来临时存储和处理大量信息的全局变量非常值得关注。如果你必须使用全局变量来存储大量数据,那么,请确保在使用完之后,对其赋值为 null 或者重新分配。
2:被忘记的 Timers 或者 callbacks
在 JavaScript 中使用 setInterval 非常常见。
大多数库都会提供观察者或者其它工具来处理回调函数,在他们自己的实例变为不可达时,会让回调函数也变为不可达的。对于 setInterval,下面这样的代码是非常常见的:
var serverData = loadData();
setInterval(function() {
var renderer = document.getElementById('renderer');
if(renderer) {
renderer.innerHTML = JSON.stringify(serverData);
}
}, 5000); //This will be executed every ~5 seconds.
这个例子阐述着 timers 可能发生的情况:计时器会引用不再需要的节点或数据。
renderer 可能在将来会被移除,使得 interval 内的整个块都不再被需要。但是,interval handler 因为 interval 的存活,所以无法被回收(需要停止 interval,才能回收)。如果 interval handler 无法被回收,则它的依赖也不能被回收。这意味着 serverData——可能存储了大量数据,也不能被回收。在观察者模式下,重要的是在他们不再被需要的时候显式地去删除它们(或者让相关对象变为不可达)。
过去,特别是某些浏览器(IE6)无法管理循环引用。如今,大多数浏览器会在被观察的对象不可达时对 observer handlers 进行回收,即使 listener 没有被显式的移除。但是,明确地删除这些 observers 仍然是一个很好的做法。例如:
var element = document.getElementById('launch-button');
var counter = 0;
function onClick(event) {
counter++;
element.innerHtml = 'text ' + counter;
}
element.addEventListener('click', onClick);
// Do stuff
element.removeEventListener('click', onClick);
element.parentNode.removeChild(element);
// Now when element goes out of scope,
// both element and onClick will be collected even in old browsers // that don't handle cycles well.
如今,现代浏览器(包括 IE 和 Edge)都使用的是现代垃圾回收算法,可以检测这些循环依赖并正确的处理它们。换句话说,让一个节点不可达,可以不必而在调用 removeEventListener。
框架和库,例如 jQuery ,在处理掉节点之前会删除 listeners (使用它们特定的 API)。这些由库的内部进了处理,确保泄漏不会发生。即使是在有问题的浏览器下运行,如。。。。IE6。
3:闭包
JavaScript 开发的一个关键方面就是闭包:一个可以访问外部(封闭)函数变量的内部函数。由于 JavaScript 运行时的实现细节,可以通过以下方式泄漏内存:
var theThing = null;
var replaceThing = function () {
var originalThing = theThing;
var unused = function () {
if (originalThing) // a reference to 'originalThing'
console.log("hi");
};
theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log("message");
}
};
};
setInterval(replaceThing, 1000);
这个代码片段做了一件事:每次调用 replaceThing 时,theThing 都会获得一个新对象,它包含一个大的数组和一个新的闭包(someMethod)。同时,变量 unused 保留了一个拥有 originalThing 引用的闭包(前一次调用 theThing 赋值给了 originalThing)。已经有点混乱了吗?重要的是,一旦一个作用域被创建为闭包,那么它的父作用域将被共享 。
在这个例子中,创建闭包 someMethod 的作用域是于 unused 共享的。unused 拥有 originalThing 的引用。尽管 unused 从来都没有使用,但是 someMethod 能够通过 theThing 在 replaceThing 之外的作用域使用(例如全局范围)。并且由于 someMethod 和 unused 共享 闭包范围,unused 的引用将强制保持 originalThing 处于活动状态(两个闭包之间共享整个作用域)。这样防止了垃圾回收。 当这段代码重复执行时,可以观察到内存使用量的稳定增长。当 GC 运行时,也没有变小。实质上,引擎创建了一个闭包的链接列表(root 就是变量 theThing),并且这些闭包的作用域中每一个都有对大数组的间接引用,导致了相当大的内存泄漏,如下图:
这个问题由 Meteor 团队发现的,他们有一篇伟大的文章,详细描述了这个问题。
4:DOM 引用
有时候,在数据结构中存储 DOM 结构是有用的。假设要快速更新表中的几行内容。将每行 DOM 的引用存储在字典或数组中可能是有意义的。当这种情况发生时,就会保留同一 DOM 元素的两份引用:一个在 DOM 树中,另一个在字典中。如果将来某个时候你决定要删除这些行,则需要让两个引用都不可达。
var elements = {
button: document.getElementById('button'),
image: document.getElementById('image')
};
function doStuff() {
elements.image.src = 'http://example.com/image_name.png';
}
function removeImage() {
// The image is a direct child of the body element.
document.body.removeChild(document.getElementById('image'));
// At this point, we still have a reference to #button in the
//global elements object. In other words, the button element is
//still in memory and cannot be collected by the GC.
}
还有一个额外的考虑,当涉及 DOM 树内部或叶子节点的引用时,必须考虑这一点。假设你在 JavaScript 代码中保留了对 table 特定单元格()的引用。有一天,你决定从 DOM 中删除该 table,但扔保留着对该单元格的引用。直观地来看,可以假设 GC 将收集除了该单元格之外所有的内容。实际上,这不会发生的:该单元格是该 table 的子节点,并且 children 保持着对它们 parents 的引用。也就是说,在 JavaScript 代码中对单元格的引用会导致整个表都保留在内存中的。保留 DOM 元素的引用时,需要仔细考虑。
==============================
原文地址:传送门 作者:Alexander Zlatkov
你可能感兴趣的:(JavaScript 工作原理(一)——内存管理与四种常见内存泄漏的处理方法)
python 读excel每行替换_Python脚本操作Excel实现批量替换功能
weixin_39646695
python 读excel每行替换
Python脚本操作Excel实现批量替换功能大家好,给大家分享下如何使用Python脚本操作Excel实现批量替换。使用的工具Openpyxl,一个处理excel的python库,处理excel,其实针对的就是WorkBook,Sheet,Cell这三个最根本的元素~明确需求原始excel如下我们的目标是把下面excel工作表的sheet1表页A列的内容“替换我吧”批量替换为B列的“我用来替换的
x86-64汇编语言训练程序与实战
十除以十等于一
本文还有配套的精品资源,点击获取简介:汇编语言是一种低级语言,与机器代码紧密相关,特别适用于编写系统级代码及性能要求高的应用。nasm编译器是针对x86和x86-64架构的汇编语言编译器,支持多种语法风格和指令集。项目Euler提供数学和计算机科学问题,鼓励编程技巧应用,前100个问题的答案可共享。x86-64架构扩展了寄存器数量并引入新指令,提升了数据处理效率。学习汇编语言能够深入理解计算机底层
男士护肤品哪个牌子好?十大男士护肤品排行榜
高省APP珊珊
很多男生意识到护肤的必要性,开始着手护肤,但不知道该选哪个男士护肤品品牌使用好。目前市面上很多男士护肤品品牌,可谓琳琅满目,让人眼花缭乱。男士挑选护肤品时,根据自己皮肤需求去正规渠道挑选合适的知名护肤品比较放心靠谱。高省APP,是2021年推出的平台,0投资,0风险、高省APP佣金更高,模式更好,终端用户不流失。【高省】是一个自用省钱佣金高,分享推广赚钱多的平台,百度有几百万篇报道,也期待你的加入
三菱PLC全套学习资料及应用手册
good2know
本文还有配套的精品资源,点击获取简介:三菱PLC作为工业自动化领域的核心设备,其系列产品的学习和应用需要全面深入的知识。本次资料包为学习者提供从基础到进阶的全方位学习资源,包括各种型号PLC的操作手册、编程指南、软件操作教程以及实际案例分析,旨在帮助用户系统掌握PLC的编程语言、指令系统及在各类工业应用中的实施。1.三菱PLC基础知识入门1.1PLC的基本概念可编程逻辑控制器(PLC)是工业自动化
2022-10-20
体力劳动者
不因感觉稍纵即逝就不加记录。在女儿睡觉后我记下今天的小故事。接手新班级后,今天是第二次收到家长的感谢信(微信)。是我表扬次数最多的两位学生家长致来的感谢,他们明显感受到孩子自信、阳光了不少,写作业由被动变为了主动,家庭氛围也由鸡飞狗跳变成了其乐融融。在被顽皮的学生气得头晕之后,我感到了久违的价值感,责任感甚至使命感,我回复家长这样一句话:我们也需要家长的反馈好让我们的教育工作更有劲头。我也认识到,
程翔授《评价一篇记叙文》
行吟斯基
桂林十一中高一2中学生自读程老师学生文章板书课题师巡看。看完举手。问:它是记叙文。不商量。独立打分。学生评价打分。师:高低都正常,不受干扰。师巡,略评。打完举手。调查:分层次举手——高分先举手。最低分。最高95分。最低45分。女:差距太大!师:同一篇,相差55分。若是你的文章,愿落谁手?男:身临其境感觉。师:你有此经历?没也没关系。女:不优美……,结尾无升华……无感悟……师:辞藻不美?(师追问)男
《玉骨遥》:大司命为什么不杀朱颜?原因没那么简单
windy天意晚晴
《玉骨遥》里,朱颜就是时影的命劫之人。重明与时影早就知道,他们一直瞒着大司命,如今大司命也知道了真相。可是大司命却没有杀朱颜,而是给朱颜下了诛心咒,还说时影的命劫已经破了,真的如此吗?1、计划总是赶不上变化的大司命从目前剧情来说,大司命还不如时影,他信心十足的事情总会有纰漏。他不让时影见命劫之女,结果时影还是遇上了。他想让时影走火入魔,一心复仇,结果时影在朱颜的劝说下放下了仇恨。大司命让时影开山收
移动端城市区县二级联动选择功能实现包
good2know
本文还有配套的精品资源,点击获取简介:本项目是一套为移动端设计的jQuery实现方案,用于简化用户在选择城市和区县时的流程。它包括所有必需文件:HTML、JavaScript、CSS及图片资源。通过动态更新下拉菜单选项,实现城市到区县的联动效果,支持数据异步加载。开发者可以轻松集成此功能到移动网站或应用,并可基于需求进行扩展和优化。1.jQuery移动端解决方案概述jQuery技术简介jQuery
日更006 终极训练营day3
懒cici
人生创业课(2)今天的主题:学习方法一:遇到有用的书,反复读,然后结合自身实际,列践行清单,不要再写读书笔记思考这本书与我有什么关系,我在哪些地方能用到,之后我该怎么用方法二:读完书没映像怎么办?训练你的大脑,方法:每读完一遍书,立马合上书,做一场分享,几分钟都行对自己的学习要求太低,要逼自己方法三:学习深度不够怎么办?找到细分领域的榜样,把他们的文章、书籍、产品都体验一遍,成为他们的超级用户,向
自律打卡第四天:比昨天进步一点点
花儿的念想
今天新闻我们县城又确诊了一例,截止目前已经确诊的三例了,打开,看了一篇简友写的武汉的真实情况,有病住不了院,还没等到床位已经去世的消息,心里更加的难受,武汉尚且这样,如果是我们这没有高速没有火车的十八线的小县城发生这种情况,那情况将是更加的不堪设想,不敢想,唯有祈求灾难早点快去,平安才是最大的福气。突然觉得我的自律打卡,比昨天进步一点点。更希望疫情战争每一天都要比昨天好一点,希望一觉醒来听到的是好
15个小技巧,让我的Windows电脑更好用了!
曹元_
01.桌面及文档处理第一部分的技巧,主要是围绕桌面的一些基本操作,包括主题设置、常用文档文件快捷打开的多种方式等等。主题换色默认情况下,我们的Win界面可能就是白色的文档界面,天蓝色的图表背景,说不出哪里不好看,但是就是觉得不够高级。imageimage说到高级感,本能第一反应就会和暗色模式联想起来,如果我们将整个界面换成黑夜模式的话,它会是这样的。imageimage更改主题颜色及暗色模式,我们
(二)SAP Group Reporting (GR) 核心子模块功能及数据流向架构解析
数据如何从子公司流转到合并报表的全过程,即数据采集→合并引擎→报表输出,特别是HANA内存计算如何优化传统ETL瓶颈。SAPGroupReporting(GR)核心模块功能及数据流向的架构解析,涵盖核心组件、数据处理流程和关键集成点,适用于S/4HANA1809+版本:一、核心功能模块概览模块功能关键事务码/FioriApp数据采集(DataCollection)整合子公司财务数据(SAP/非SA
9、汇编语言编程入门:从环境搭建到简单程序实现
神经网络酱
汇编语言 MEPIS GNU工具链
汇编语言编程入门:从环境搭建到简单程序实现1.数据存储介质问题解决在处理数据存储时,若要使用MEPIS系统,需确保有其可访问的存储介质。目前,MEPIS无法向采用NTFS格式(常用于Windows2000和XP工作站)的硬盘写入数据。不过,若硬盘采用FAT32格式,MEPIS就能进行写入操作。此外,MEPIS还能将文件写入软盘和大多数USB闪存驱动器。若工作站连接到局域网,还可通过FTP协议或挂载
月光下的罪恶(5)
允歌玖沐
5.被孤立顾纨是转校过来的,进入学校后,回头率很高“诶诶诶,你看那女生,哪个系的?”“不知道没见过。”“看那样,一看就是个胆小的货。”顾纨当做没听到,更狠的话她都听过,更何况女生们耍心眼?“他爸爸是做黑生意的,估计女儿也不是什么好的,你以后离他一家子远点。”她走向自己要上课的教室,一进门,所有人的目光看向她,顾纨若无其事的走进教室,开始上课。下课,一群人站起来,但是很显然,她周围的一圈人都不愿意和
day15|前端框架学习和算法
universe_01
前端 算法 笔记
T22括号生成先把所有情况都画出来,然后(在满足什么情况下)把不符合条件的删除。T78子集要画树状图,把思路清晰。可以用暴力法、回溯法和DFS做这个题DFS深度搜索:每个边都走完,再回溯应用:二叉树搜索,图搜索回溯算法=DFS+剪枝T200岛屿数量(非常经典BFS宽度把树状转化成队列形式,lambda匿名函数“一次性的小函数,没有名字”setup语法糖:让代码更简洁好写的语法ref创建:基本类型的
贝多芬诞辰250周年纪念
万千星河赴远方
就算不是古典音乐爱好者,你也一定听说过贝多芬。作为古典音乐史上最伟大的音乐家之一,他不仅是古典主义风格的集大成者,同时也是浪漫主义风格的开创者。贝多芬肖像画(1813年)贝多芬的一生共创作了9部交响曲、36首钢琴奏鸣曲、10部小提琴奏鸣曲、16首弦乐四重奏、1部歌剧及2部弥撒曲等等。数量虽然不及前辈海顿、莫扎特多,但他几乎改造了当时所有的音乐表达形式,赋予了它们全新的价值,对后世音乐的发展产生了极
IK分词
初心myp
实现简单的分词功能,智能化分词添加依赖配置:4.10.4org.apache.lucenelucene-core${lucene.version}org.apache.lucenelucene-analyzers-common${lucene.version}org.apache.lucenelucene-queryparser${lucene.version}org.apache.lucenel
三件事—小白猫·雨天·八段锦
咸鱼月亮
1.最近楼下出现一只非常漂亮的粘人小白猫,看着不像是流浪猫,非常亲人。眼睛比蓝球的还大,而且是绿色的,很漂亮。第一次遇到它,它就跟我到电梯口,如果我稍微招招手,肯定就跟我进电梯了。后来我喂过它几次,好可惜不能养它,一只蓝球就是我的极限了。2.下雨天就心烦,好奇怪。明明以前我超爱看窗外的雨和听雨声,看来近来的心情不够宁静了。3.最近在练八段锦,从第一次就爱上了这个运动,很轻松缓慢,但是却出汗。感觉可
25-1-2019
树藤与海岛呢
hello八月来报道了今天看到了一篇文章就只想记下那两句话:良田千顷不过一日三餐广夏万间只睡卧榻三尺大概的意思就是要珍惜当下不要等来不及的时候才珍惜分享今天的两餐最近没有时间运动呢下个月补回好了说完了哈哈goodnight图片发自App图片发自App
《极简思维》第三部分
小洋苏兮
整理你的人际关系如何改善人际关系?摘录:因为人际关系问题是人们生活中不快乐的主要原因。感想:感觉这个说的挺对,之前我总是埋头学习,不管舍友不管自己的合作伙伴的一些事情,但实际上,这学期关注了之后好多了摘录:“亲密关系与社交会让你健康而快乐。这是基础。太过于关注成就或不太关心人际关系的人都不怎么快乐。基本上来说,人类就是建立在人脉关系上的。”感想:但是如果有时想的太多就不太好,要以一个开放的心态跟别
力扣热题100-------54. 螺旋矩阵
海航Java之路
力扣 leetcode 矩阵 java
给你一个m行n列的矩阵matrix,请按照顺时针螺旋顺序,返回矩阵中的所有元素。示例1:输入:matrix=[[1,2,3],[4,5,6],[7,8,9]]输出:[1,2,3,6,9,8,7,4,5]示例2:输入:matrix=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]输出:[1,2,3,4,8,12,11,10,9,5,6,7]提示:m==matrix.lengthn
我不懂什么是爱,但我给你全部我拥有的
香尧
因为怕黑,所以愿意陪伴在夜中行走的人,给他一点点的安全感。因为渴望温柔与爱,所以愿意为别的孩子付出爱与温柔。因为曾遭受侮辱和伤害,所以不以同样的方式施于其他人。如果你向别人出之以利刃,对方还了你爱与包容,真的不要感激他,真的不要赞美他。每一个被人伤害过的人心里都留下了一颗仇恨的种子,他也会想要有一天以眼还眼,以牙还牙。但他未让那颗种子生根发芽,他用一把心剑又一次刺向他自己,用他血荐仇恨,开出一朵温
你要记住,最重要的是:随时做好准备,为了你可能成为更好的自己,放弃现在的自己。
霖霖z
打卡人:周云日期:2018年11月09日【日精进打卡第180天】【知~学习】《六项精进》0遍共214遍《通篇》1遍共106遍《大学》2遍共347遍《坚强工作,温柔生活》ok《不抱怨的世界》104-108页《经典名句》你要记住,最重要的是:随时做好准备,为了你可能成为更好的自己,放弃现在的自己。【行~实践】一、修身:(对自己个人)1、坚持打卡二、齐家:(对家庭和家人)打扫卫生,接送孩子,洗衣做饭,陪
SpringMVC执行流程(原理),通俗易懂
国服冰
SpringMVC spring mvc
SpringMVC执行流程(原理),通俗易懂一、图解SpringMVC流程二、进一步理解Springmvc的执行流程1、导入依赖2、建立展示的视图3、web.xml4、spring配置文件springmvc-servlet5、Controller6、tomcat配置7、访问的url8、视图页面一、图解SpringMVC流程图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提
C++ 计数排序、归并排序、快速排序
每天搬一点点砖
c++ 数据结构 算法
计数排序:是一种基于哈希的排序算法。他的基本思想是通过统计每个元素的出现次数,然后根据统计结果将元素依次放入排序后的序列中。这种排序算法适用于范围较小的情况,例如整数范围在0到k之间计数排序步骤:1初始化一个长度为最大元素值加1的计数数组,所有元素初始化为02遍历原始数组,将每个元素值作为索引,在计数数组中对应位置加13将数组清空4遍历计数器数组,按照数组中的元素个数放回到元数组中计数排序的优点和
现在发挥你的优势
爱生活的佑嘉
来和我做咨询的一些朋友,涉及到定位的,都会说,我不知道我的优势是什么,你能不能帮我看看?还有一些朋友,喜欢做各种测试来了解自己,测试过后,然并卵。今天,我想来聊聊优势,如何能了解自己的优势是什么。首先,我们要知道,如果要成为“不一般”的人,我们所做的事情,就要基于自身的优势。我做管理者十多年,看到每个员工都有不同的特长,有的擅长数字,有的擅长人际,有的擅长写作。这些知道自己优势并且在这方面刻意练习
2023-11-02
一帆f
发现浸润心田的感觉:今天一个机缘之下突然想分享我的婆媳关系,我一边分享一边回忆我之前和儿媳妇关系的微妙变化,特别是分享到我能感受到儿媳妇的各种美好,现在也能心平气和的和老公平等对话,看到自己看到老公,以己推人以人推己自然而然的换位思考,心中有一种美好的能量在涌动,一种浸润心田的感觉从心胸向全身扩散,美好极了……我很想记住这种感觉,赶紧把它写下来以留纪念,也就是当我看见他人的美好,美好的美妙的浸润心
贫穷家庭的孩子考上985以后会怎样?
Mellisa蜜思言
我出生在一个贫穷的农村家庭,据我妈说,我出生的时候才4斤多,而她生完我以后月子里就瘦到70斤。家里一直很穷,父母都是在菜市场卖菜的,家里还有几亩地种庄稼的。我很小开始就要去帮忙,暑假的生活就是帮忙去卖菜和割稻谷,那时候自己对于割稻谷这种事情有着莫名的恐惧,生怕自己长大以后还是每年都要过着割稻谷这种日子。父母因为忙于生计无暇顾及我的学习,幸好我因为看到他们这样子的生活,内心里有深深的恐惧感,驱使着我
实时数据流计算引擎Flink和Spark剖析
程小舰
flink spark 数据库 kafka hadoop
在过去几年,业界的主流流计算引擎大多采用SparkStreaming,随着近两年Flink的快速发展,Flink的使用也越来越广泛。与此同时,Spark针对SparkStreaming的不足,也继而推出了新的流计算组件。本文旨在深入分析不同的流计算引擎的内在机制和功能特点,为流处理场景的选型提供参考。(DLab数据实验室w.x.公众号出品)一.SparkStreamingSparkStreamin
密码正则验证:大小写字母、数字、特殊字符至少8位
qq_21875331
渐进式的成长
正则表达式:密码必须包含大写字母、数字、特殊字符(四种里至少三种,且至少8位)写法一:/((^(?=.*[a-z])(?=.*[A-Z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^(?=.*\d)(?=.*[A-Z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^(?=.*\d)(?=.*[a-z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^
ztree设置禁用节点
3213213333332132
JavaScript ztree json setDisabledNode Ajax
ztree设置禁用节点的时候注意,当使用ajax后台请求数据,必须要设置为同步获取数据,否者会获取不到节点对象,导致设置禁用没有效果。
$(function(){
showTree();
setDisabledNode();
});
JVM patch by Taobao
bookjovi
java HotSpot
在网上无意中看到淘宝提交的hotspot patch,共四个,有意思,记录一下。
7050685:jsdbproc64.sh has a typo in the package name
7058036:FieldsAllocationStyle=2 does not work in 32-bit VM
7060619:C1 should respect inline and
将session存储到数据库中
dcj3sjt126com
sql PHP session
CREATE TABLE sessions (
id CHAR(32) NOT NULL,
data TEXT,
last_accessed TIMESTAMP NOT NULL,
PRIMARY KEY (id)
);
<?php
/**
* Created by PhpStorm.
* User: michaeldu
* Date
Vector
171815164
vector
public Vector<CartProduct> delCart(Vector<CartProduct> cart, String id) {
for (int i = 0; i < cart.size(); i++) {
if (cart.get(i).getId().equals(id)) {
cart.remove(i);
各连接池配置参数比较
g21121
连接池
排版真心费劲,大家凑合看下吧,见谅~
Druid
DBCP
C3P0
Proxool
数据库用户名称 Username Username User
数据库密码 Password Password Password
驱动名
[简单]mybatis insert语句添加动态字段
53873039oycg
mybatis
mysql数据库,id自增,配置如下:
<insert id="saveTestTb" useGeneratedKeys="true" keyProperty="id"
parameterType=&
struts2拦截器配置
云端月影
struts2拦截器
struts2拦截器interceptor的三种配置方法
方法1. 普通配置法
<struts>
<package name="struts2" extends="struts-default">
&
IE中页面不居中,火狐谷歌等正常
aijuans
IE中页面不居中
问题是首页在火狐、谷歌、所有IE中正常显示,列表页的页面在火狐谷歌中正常,在IE6、7、8中都不中,觉得可能那个地方设置的让IE系列都不认识,仔细查看后发现,列表页中没写HTML模板部分没有添加DTD定义,就是<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3
String,int,Integer,char 几个类型常见转换
antonyup_2006
html sql .net
如何将字串 String 转换成整数 int?
int i = Integer.valueOf(my_str).intValue();
int i=Integer.parseInt(str);
如何将字串 String 转换成Integer ?
Integer integer=Integer.valueOf(str);
如何将整数 int 转换成字串 String ?
1.
PL/SQL的游标类型
百合不是茶
显示游标(静态游标) 隐式游标 游标的更新和删除 %rowtype ref游标(动态游标)
游标是oracle中的一个结果集,用于存放查询的结果;
PL/SQL中游标的声明;
1,声明游标
2,打开游标(默认是关闭的);
3,提取数据
4,关闭游标
注意的要点:游标必须声明在declare中,使用open打开游标,fetch取游标中的数据,close关闭游标
隐式游标:主要是对DML数据的操作隐
JUnit4中@AfterClass @BeforeClass @after @before的区别对比
bijian1013
JUnit4 单元测试
一.基础知识
JUnit4使用Java5中的注解(annotation),以下是JUnit4常用的几个annotation: @Before:初始化方法 对于每一个测试方法都要执行一次(注意与BeforeClass区别,后者是对于所有方法执行一次)@After:释放资源 对于每一个测试方法都要执行一次(注意与AfterClass区别,后者是对于所有方法执行一次
精通Oracle10编程SQL(12)开发包
bijian1013
oracle 数据库 plsql
/*
*开发包
*包用于逻辑组合相关的PL/SQL类型(例如TABLE类型和RECORD类型)、PL/SQL项(例如游标和游标变量)和PL/SQL子程序(例如过程和函数)
*/
--包用于逻辑组合相关的PL/SQL类型、项和子程序,它由包规范和包体两部分组成
--建立包规范:包规范实际是包与应用程序之间的接口,它用于定义包的公用组件,包括常量、变量、游标、过程和函数等
--在包规
【EhCache二】ehcache.xml配置详解
bit1129
ehcache.xml
在ehcache官网上找了多次,终于找到ehcache.xml配置元素和属性的含义说明文档了,这个文档包含在ehcache.xml的注释中!
ehcache.xml : http://ehcache.org/ehcache.xml
ehcache.xsd : http://ehcache.org/ehcache.xsd
ehcache配置文件的根元素是ehcahe
ehcac
java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderL
白糖_
java eclipse spring tomcat Web
今天学习spring+cxf的时候遇到一个问题:在web.xml中配置了spring的上下文监听器:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
随后启动
angular.element
boyitech
AngularJS AngularJS API angular.element
angular.element
描述: 包裹着一部分DOM element或者是HTML字符串,把它作为一个jQuery元素来处理。(类似于jQuery的选择器啦) 如果jQuery被引入了,则angular.element就可以看作是jQuery选择器,选择的对象可以使用jQuery的函数;如果jQuery不可用,angular.e
java-给定两个已排序序列,找出共同的元素。
bylijinnan
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CommonItemInTwoSortedArray {
/**
* 题目:给定两个已排序序列,找出共同的元素。
* 1.定义两个指针分别指向序列的开始。
* 如果指向的两个元素
sftp 异常,有遇到的吗?求解
Chen.H
java jcraft auth jsch jschexception
com.jcraft.jsch.JSchException: Auth cancel
at com.jcraft.jsch.Session.connect(Session.java:460)
at com.jcraft.jsch.Session.connect(Session.java:154)
at cn.vivame.util.ftp.SftpServerAccess.connec
[生物智能与人工智能]神经元中的电化学结构代表什么?
comsci
人工智能
我这里做一个大胆的猜想,生物神经网络中的神经元中包含着一些化学和类似电路的结构,这些结构通常用来扮演类似我们在拓扑分析系统中的节点嵌入方程一样,使得我们的神经网络产生智能判断的能力,而这些嵌入到节点中的方程同时也扮演着"经验"的角色....
我们可以尝试一下...在某些神经
通过LAC和CID获取经纬度信息
dai_lm
lac cid
方法1:
用浏览器打开http://www.minigps.net/cellsearch.html,然后输入lac和cid信息(mcc和mnc可以填0),如果数据正确就可以获得相应的经纬度
方法2:
发送HTTP请求到http://www.open-electronics.org/celltrack/cell.php?hex=0&lac=<lac>&cid=&
JAVA的困难分析
datamachine
java
前段时间转了一篇SQL的文章(http://datamachine.iteye.com/blog/1971896),文章不复杂,但思想深刻,就顺便思考了一下java的不足,当砖头丢出来,希望引点和田玉。
-----------------------------------------------------------------------------------------
小学5年级英语单词背诵第二课
dcj3sjt126com
english word
money 钱
paper 纸
speak 讲,说
tell 告诉
remember 记得,想起
knock 敲,击,打
question 问题
number 数字,号码
learn 学会,学习
street 街道
carry 搬运,携带
send 发送,邮寄,发射
must 必须
light 灯,光线,轻的
front
linux下面没有tree命令
dcj3sjt126com
linux
centos p安装
yum -y install tree
mac os安装
brew install tree
首先来看tree的用法
tree 中文解释:tree
功能说明:以树状图列出目录的内容。
语 法:tree [-aACdDfFgilnNpqstux][-I <范本样式>][-P <范本样式
Map迭代方式,Map迭代,Map循环
蕃薯耀
Map循环 Map迭代 Map迭代方式
Map迭代方式,Map迭代,Map循环
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
蕃薯耀 2015年
Spring Cache注解+Redis
hanqunfeng
spring
Spring3.1 Cache注解
依赖jar包:
<!-- redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
Guava中针对集合的 filter和过滤功能
jackyrong
filter
在guava库中,自带了过滤器(filter)的功能,可以用来对collection 进行过滤,先看例子:
@Test
public void whenFilterWithIterables_thenFiltered() {
List<String> names = Lists.newArrayList("John"
学习编程那点事
lampcy
编程 android PHP html5
一年前的夏天,我还在纠结要不要改行,要不要去学php?能学到真本事吗?改行能成功吗?太多的问题,我终于不顾一切,下定决心,辞去了工作,来到传说中的帝都。老师给的乘车方式还算有效,很顺利的就到了学校,赶巧了,正好学校搬到了新校区。先安顿了下来,过了个轻松的周末,第一次到帝都,逛逛吧!
接下来的周一,是我噩梦的开始,学习内容对我这个零基础的人来说,除了勉强完成老师布置的作业外,我已经没有时间和精力去
架构师之流处理---------bytebuffer的mark,limit和flip
nannan408
ByteBuffer
1.前言。
如题,limit其实就是可以读取的字节长度的意思,flip是清空的意思,mark是标记的意思 。
2.例子.
例子代码:
String str = "helloWorld";
ByteBuffer buff = ByteBuffer.wrap(str.getBytes());
Sy
org.apache.el.parser.ParseException: Encountered " ":" ": "" at line 1, column 1
Everyday都不同
$ 转义 el表达式
最近在做Highcharts的过程中,在写js时,出现了以下异常:
严重: Servlet.service() for servlet jsp threw exception
org.apache.el.parser.ParseException: Encountered " ":" ": "" at line 1,
用Java实现发送邮件到163
tntxia
java实现
/*
在java版经常看到有人问如何用javamail发送邮件?如何接收邮件?如何访问多个文件夹等。问题零散,而历史的回复早已经淹没在问题的海洋之中。
本人之前所做过一个java项目,其中包含有WebMail功能,当初为用java实现而对javamail摸索了一段时间,总算有点收获。看到论坛中的经常有此方面的问题,因此把我的一些经验帖出来,希望对大家有些帮助。
此篇仅介绍用
探索实体类存在的真正意义
java小叶檀
POJO
一. 实体类简述
实体类其实就是俗称的POJO,这种类一般不实现特殊框架下的接口,在程序中仅作为数据容器用来持久化存储数据用的
POJO(Plain Old Java Objects)简单的Java对象
它的一般格式就是
public class A{
private String id;
public Str