07/27~08/02周报

本文深入探讨JavaScript的基础知识,涵盖JS的特点、数据类型、在HTML中的应用、基本语法、变量定义、数据类型检测、操作符、语句、函数、变量作用域、内存管理、引用类型详解、数组操作、日期与正则表达式处理、函数类型解析,以及基本包装类型的功能,为初学者提供全面的JS入门指南。

【本周任务】
学习JS前七章
1.JS特点
解释性语言、单线程(同一时间只能完成一项)
2.JS数据类型
原始值(stack栈内存,先进后出):Number、Boolean、String、Undefine、Null
引用值(heap堆内存):array、object、function…
3.在html中使用JavaScript(在< /body >标签前)
直接嵌入

<script type="text/javascript"> 
function sayHi(){ 
alert("Hi!"); 
} 
</script> 
外部文件
<script type="text/javascript" src="example.js"></script> 

基本概念

1.类似C语言,区分大小写
标识符:第一个字符必须是一个字母、下划线(_)或一个美元符号($); 其他字符可以是字母、下划线、美元符号或数字。采用驼峰大小写格式(myCar)。不能是关键字、保留字、true、false和null。
2.注释方法同C语言(//)或(/* */)。
3.语句同C语言,以;结尾或}结尾
4.变量:
(1)定义变量: var car;
(2)定义+初始化: var car = “my”;
(3)省略var可以定义全局变量,但不推荐
(4)可以使用一条语句定义多个变量,且因为ECMAScript是松散类型,使用不同类型初始化变量的操作可以放在一条语句中来完成。

var message = "hi", 
found = false, 
age = 29; 

5.数据类型
(1)基本数据类型:Undefined、Null、Boolean、Number、String。
(2)复杂数据类型:object
(3)typeof操作符:用于检测给定变量的数据类型

var message = "some string"; 
alert(typeof message); // "string" 

(5)Undefined类型
在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined。不存在需要显式地把一个变量设置为 undefined 值。
(6)Null类型
null 值表示一个空对象指针。

var car = null; 
alert(typeof car); // "object" 

如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null 而不是其他值。这样一来,只要直接检查 null 值就可以知道相应的变量是否已经保存了一个对象的引用。

if (car != null){ 
// 对 car 对象执行某些操作 
} 

(7)Boolean类型
只有两个字面值:true 和 false。(区分大小写)要将一个值转换为其对应的 Boolean 值,可以调用转型函数 Boolean()。
转换规则:
数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 “”(空字符串)
Number 任何非零数字值(包括无穷大) 0和NaN
Object 任何对象 null
Undefined n/a(不适用) undefined
(8)Number类型
支持十进制、八进制和十六进制(同C语言)
浮点数计算精度不如整数,因此

if (a + b == 0.3){ // 不要做这样的测试! 
alert("You got 0.3."); 
} 

NaN,非数值,不会抛出错误。
IsNaN()函数确定参数是否“不是数值”
Number()函数、parseInt(函数)、parsefloat()函数数值转换
(9)string类型
toString()函数(不能转换null和undefined)、String()函数为字符串转换函数。
6.操作符
(1)递增递减操作符
(2)按位非、按位与、按位或、按位异或、左移、右移
(3)逻辑非、逻辑与、逻辑或
(4)乘法、除法、求模
(5)加法、减法
(6)关系操作符
(7)相等与不相等、全等和不全等
(8)条件操作符
(9)赋值操作符
(10)逗号操作符
7.语句
1)if
(2)do-while
(3)while
(4)for(于 ECMAScript 中不存在块级作用
域,因此在循环内部定义的变量也可以在外部访问到)
(5)for-in
如果表示要迭代的对象的变量值为 null 或 undefined,for-in 语句不执行循环体。
(6)label(可以在代码中添加标签)
一般都要与 for 语句等循环语句配合使用,由 break 或 continue 语句引用,跳出指定循环。
(7)break和continue
(8)with(将代码的作用域设置到一个特定的对象中)
(9)switch
switch 语句中使用任何数据类型(在很多其他语言中只能使用数值),无论是字符串,还是对象都没有问题。每个 case 的值不一定是常量,可以是变量,甚至是表达式。比较时使用全等操作符,不会发生类型转换。
8.函数
(1)参数
ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。函数参数是以一个包含零或多个值的数组的形式传递的。在函数体内可以通过 arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。
(2)没有重载
如果在 ECMAScript 中定义了两个名字相同的函数,则该名字只属于后定义的函数

变量、作用域和内存问题

1.两种类型:基本类型和引用类型(可以为其添加属性和方法,也可以改变删除其属性和方法,动态地添加属性)
2.动态的属性:引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法,不能给基本类型的值添加属性
3.复制变量:复制基本类型的值,复制后互不影响,复制引用类型的值时,改变一个变量,另一个就会受到影响
4.传递函数:ECMAScript 中所有函数的参数都是按值传递的。
5.检测类型(instanceof 操作符):alert(person instanceof Object); // 变量 person 是 Object 吗?
6.执行环境及作用域
在局部作用域中定义的变量可以在局部环境中与全局变量互换使用,每个环境都 可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个 执行环境。
7.延长作用域链
try-catch 语句的 catch 块;
with 语句。
8.JavaScript 没有块级作用域,使用 var 声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境;在 with 语句中,最接近的环境是函数环境。如果初始化变量时没有使用 var 声明,该变量会自动被添加到全局环境。在初始化变量之前,一定要先声明。
9.查询标识符
搜索过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。如果在局部环境中找到
了该标识符,搜索过程停止,变量就绪。如果在局部环境中没有找到该变量名,则继续沿作用域链向上搜索。搜索过程将一直追溯到全局环境的变量对象。
10.JavaScript 具有自动垃圾收集机制
垃圾收集:标记清除和引用计数(循环引用会出现问题)
11.管理内存:一旦数据不再有用,最好通过将其值设置为 null 来释放其引用,这个做法叫做解除引用,解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
12.执行环境有全局执行环境和函数执行环境之分
13.基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中,引用类型的值是对象,保存在堆内存中。

引用类型

引用类型是一种数据结构,用于将数据和功能组织在一起。引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
1.object类型
(1)创建方法:第一种是使用 new 操作符后跟 Object 构造函数,第二种是使用对象字面量表示法(推荐使用)。

var person = { 
name : "Nicholas", 
age : 29 
}; 

(2)访问对象属性:一般来说,访问对象属性时使用的都是点表示法,这也是很多面向对象语言中通用的语法。不过,在 JavaScript 也可以使用方括号表示法来访问对象的属性。在使用方括号语法时,应该将要访问的属性以字符串的形式放在方括号中。方括号语法的主要优点是可以通过变量 来访问属性。如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括 号表示法。
2.Array类型
(1)创建方法:第一种是使用 Array 构造函数,第二种是使用数组字面量表示法。

var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
var values = [1,2,]; // 不要这样!这样会创建一个包含 2 或 3 项的数组 
var options = [,,,,,]; // 不要这样!这样会创建一个包含 5 或 6 项的数组

(2)Length属性(返回数组长度)
数组的 length 属性很有特点——它不是只读的,可以从数组的末尾移除项或向数组中添加新项。
(3)数组最多可以包含 4 294 967 295 个项
(4)检测数组

if (Array.isArray(value)){ 
//对数组执行某些操作 
} 

(5)转换方法
toString()、toLocaleString()、join()
(6)栈方法(后进先出)
push()末尾接收和 pop()末尾移出,返回移出项
(7)队列方法(先进先出)
shift()首项移出,返回移出项和 push()方法
unshift()在数组前端添加任意个项并返回新数组的长度和pop()
(8)重排序方法
reverse()反转数组项的顺序和 sort()
排序:

Function compare(value1,value2)
{
If(value1<value2)
{
   Return -1;
}	
If(value1>value2)
{
   Return 1;
}
else{
   Return 0;
}
}

Var values=[0,1,5,10,15];
Values.sort(compare);
Alert(values);   //0,1,5,10,15

(9)操作方法
concat()创建当前数组的副本
slice()基于当前数组中的一或多个项创建一个新数组
splice()三个参数,第一个指定位置,第二个删除个数,第三个要插入的项,返回值是数组是删除的项
(9)位置方法
indexOf()从前往后和 lastIndexOf()从后往前,都有两个参数,第一个是查找项,第二个是查找起点
(10)迭代方法
every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。
filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
forEach():对数组中的每一项运行给定函数。这个方法没有返回值。
map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。

var numbers = [1,2,3,4,5,4,3,2,1]; 
var everyResult = numbers.every(function(item, index, array){ 
return (item > 2); 
}); 
alert(everyResult); //false 

(11)归并方法
reduce()从前到后和 reduceRight()从后到前

var values = [1,2,3,4,5]; 
var sum = values.reduce(function(prev, cur, index, array){ 
return prev + cur; 
}); 
alert(sum); //15

3.Date类型
(1)创建方法:var now = new Date()
4.RegExp类型
(1)字面量形式定义正则表达式:

var expression = / pattern / flags ; 

Flag:
g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即
停止;
i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;
m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模
式匹配的项。
与其他语言中的正则表达式类似,模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:
( [ { \ ^ $ | ) ? * + .]}

/* 
* 匹配所有以"at"结尾的 3 个字符的组合,不区分大小写 
*/ 
var pattern3 = /.at/gi; 
/* 
* 匹配所有".at",不区分大小写 
*/ 
var pattern4 = /\.at/gi; 

(2)RegExp 构造函数创建正则表达式,两个参数,一个是要匹配的字符串模式,第二个是可选的标志字符串,转义时需要双重转义\
var pattern2 = new RegExp("[bc]at", "i");
5.Function类型(函数)
(1)使用不带圆括号的函数名是访问函数指针,而非调用函数。
(2)没有重载

function addSomeNumber(num){ 
return num + 100; 
} 
function addSomeNumber(num) { 
return num + 200; 
} 
var result = addSomeNumber(100); //300 

后面的函数覆盖了前面的函数
(3)函数声明
函数声明与函数表达式的语法其实是等价的

alert(sum(10,10)); 
function sum(num1, num2){   //函数声明,此处不能将function赋给sum变量
return num1 + num2; 
} 

(4)函数名本身就是变量,可以作为值进行传递,函数的嵌套
(5)使用 arguments.callee,完成递归调用,不用引用函数名
(6)this 值(引用的是函数据以执行的环境对象,当在网页的全局作用域中调用函数时,this 对象引用的就是 window)
(7)length 属性表示函数希望接收的命名参数的个数
(8)apply()和 call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。
(9)bind()。这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。
6.基本包装类型
(1)Boolean类型

var falseObject = new Boolean(false); 
var result = falseObject && true; 
alert(result); //true 

示例中的这行代码是对falseObject 而不是对它的值(false)进行求值。前面讨论过,布尔表达式中的所有对象都会被转换为 true,因此 falseObject 对象在布尔表达式中代表的是 true。

var falseValue = false; 
result = falseValue && true; 
alert(result); //false 

(2)Number类型
toString()方法传递一个表示基数的参数,告诉它返回几进制数值的字符串形式。
toFixed()方法会按照指定的小数位返回数值的字符串表示。
toExponential()e表示法
toPrecision()方法可能会返回固定大小(fixed)格式,根据参数而定
(3)String类型
var stringObject = new String(“hello world”);
属性:length长度
a.字符
charAt()访问特定字符返回字符
charCodeAt()访问特定字符返回字符编码
b.字符串
concat()用于将一或多个字符串拼接起来,可以接受多个参数(与+同)
两个参数,第一个参数是开始位置
slice()第二个参数是结束位置
substr()第二个参数是结束位置
substring()第二个参数返回个数
slice()方法会将传入的负值与字符串的长度相加,substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为 0。最后,substring()方法会把所有负值参数都转换为 0。

var stringValue = "hello world"; 
alert(stringValue.slice(-3)); //"rld" 
alert(stringValue.substring(-3)); //"hello world" 
alert(stringValue.substr(-3)); //"rld" 
alert(stringValue.slice(3, -4)); //"lo w" 
alert(stringValue.substring(3, -4)); //"hel" 
alert(stringValue.substr(3, -4)); //""(空字符串)

c.字符串位置方法(可选的第二个参数,表示从字符串中的哪个位置开始搜索)
indexOf()从头和 lastIndexOf()从尾
d.trim()方法,删除前缀和后缀空格
e.转换大小写
toLowerCase()toLocaleLowerCase()小写
toUpperCase()和 toLocaleUpperCase()大写
f.字符串模式的匹配方法
match()本质上与调用 RegExp 的 exec()方法相同
search()一个参数与 match()方法的参数相同:由字符串或 RegExp 对象指定的一个正则表达式
replace()两个参数:第一个参数可以是一个 RegExp 对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个字符串或者一个函数。
split()(分隔符)方法可以接受可选的第二个参数,用于指定数组的大小
g.字符串比较
localeCompare()
h.fromCharCode()。这个方法的任务是接收一或多个字符编码,然后将它们转换成一个字符串。
7.Globa对象
8.Math对象

对象

1.属性类型:数据属性和访问器属性,分别有四个特征,改变特征用
Object.defineProperty()方法。

var person = {}; 
Object.defineProperty(person, "name", { 
configurable: false, 
value: "Nicholas" 
}); 
alert(person.name); //"Nicholas" 
delete person.name; 
alert(person.name); //"Nicholas" 

2.Object.defineProperties()方法,定义多个属性。两个参数,一个是要添加和修改属性的对象,另一个是属性。
3.Object.getOwnPropertyDescriptor(),读取属性特征。
4.构造函数,为了避免产生重复代码,可以采用工厂模式和构造函数模式。

function createPerson(name, age, job){ 
var o = new Object(); 
o.name = name; 
o.age = age; 
o.job = job; 
o.sayName = function(){ 
alert(this.name); 
}; 
return o; 
} 
var person1 = createPerson("Nicholas", 29, "Software Engineer"); 
var person2 = createPerson("Greg", 27, "Doctor"); 

function Person(name, age, job){ 
this.name = name; 
this.age = age; 
this.job = job; 
this.sayName = function(){ 
alert(this.name); 
}; 
} 
var person1 = new Person("Nicholas", 29, "Software Engineer"); 
var person2 = new Person("Greg", 27, "Doctor"); 

5.原型模式,使用构造函数的 prototype 属性来指定那些应该共享的属性和方法。组合使用构造
函数模式和原型模式时,使用构造函数定义实例属性,而使用原型定义共享的属性和方法。
6.原型式继承,可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的浅
复制。而复制得到的副本还可以得到进一步改造。
7.寄生式继承,与原型式继承非常相似,也是基于某个对象或某些信息创建一个对象,然后增强
对象,最后返回对象。为了解决组合继承模式由于多次调用超类型构造函数而导致的低效率问
题,可以将这个模式与组合继承一起使用。
8.寄生组合式继承,集寄生式继承和组合继承的优点与一身,是实现基于类型继承的最有效方式。

函数

1.函数表达式不同于函数声明。函数声明要求有名字,但函数表达式不需要。没有名字的函数表
达式也叫做匿名函数。
2.在无法确定如何引用函数的情况下,递归函数就会变得比较复杂;
3.递归函数应该始终使用 arguments.callee 来递归地调用自身,不要使用函数名——函数名可
能会发生变化。当在函数内部定义了其他函数时,就创建了闭包。闭包有权访问包含函数内部的所有变量。在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域。
4.函数的作用域及其所有变量都会在函数执行结束后被销毁。
5.当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。使用闭包可以在 JavaScript 中模仿块级作用域。
6.即使 JavaScript 中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公
有方法可以访问在包含作用域中定义的变量。
7.有权访问私有变量的公有方法叫做特权方法。
8.可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强的模块模式来实现单例的特权方法。

AI 代码审查Review工具 是一个旨在自动化代码审查流程的工具。它通过集成版本控制系统(如 GitHub 和 GitLab)的 Webhook,利用大型语言模型(LLM)对代码变更进行分析,并将审查意见反馈到相应的 Pull Request 或 Merge Request 中。此外,它还支持将审查结果通知到企业微信等通讯工具。 一个基于 LLM 的自动化代码审查助手。通过 GitHub/GitLab Webhook 监听 PR/MR 变更,调用 AI 分析代码,并将审查意见自动评论到 PR/MR,同时支持多种通知渠道。 主要功能 多平台支持: 集成 GitHub 和 GitLab Webhook,监听 Pull Request / Merge Request 事件。 智能审查模式: 详细审查 (/github_webhook, /gitlab_webhook): AI 对每个变更文件进行分析,旨在找出具体问题。审查意见会以结构化的形式(例如,定位到特定代码行、问题分类、严重程度、分析和建议)逐条评论到 PR/MR。AI 模型会输出 JSON 格式的分析结果,系统再将其转换为多条独立的评论。 通用审查 (/github_webhook_general, /gitlab_webhook_general): AI 对每个变更文件进行整体性分析,并为每个文件生成一个 Markdown 格式的总结性评论。 自动化流程: 自动将 AI 审查意见(详细模式下为多条,通用模式下为每个文件一条)发布到 PR/MR。 在所有文件审查完毕后,自动在 PR/MR 中发布一条总结性评论。 即便 AI 未发现任何值得报告的问题,也会发布相应的友好提示和总结评论。 异步处理审查任务,快速响应 Webhook。 通过 Redis 防止对同一 Commit 的重复审查。 灵活配置: 通过环境变量设置基
【直流微电网】径向直流微电网的状态空间建模与线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模与线性化方法,重点提出了一种基于耦合DC-DC变换器的状态空间平均模型的建模策略。该方法通过数学建模手段对直流微电网系统进行精确的状态空间描述,并对其进行线性化处理,以便于系统稳定性分析与控制器设计。文中结合Matlab代码实现,展示了建模与仿真过程,有助于研究人员理解和复现相关技术,推动直流微电网系统的动态性能研究与工程应用。; 适合人群:具备电力电子、电力系统或自动化等相关背景,熟悉Matlab/Simulink仿真工具,从事新能源、微电网或智能电网研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网的动态建模方法;②学习DC-DC变换器在耦合条件下的状态空间平均建模技巧;③实现系统的线性化分析并支持后续控制器设计(如电压稳定控制、功率分配等);④为科研论文撰写、项目仿真验证提供技术支持与代码参考。; 阅读建议:建议读者结合Matlab代码逐步实践建模流程,重点关注状态变量选取、平均化处理和线性化推导过程,同时可扩展应用于更复杂的直流微电网拓扑结构中,提升系统分析与设计能力。
内容概要:本文介绍了基于物PINN驱动的三维声波波动方程求解(Matlab代码实现)理信息神经网络(PINN)求解三维声波波动方程的Matlab代码实现方法,展示了如何利用PINN技术在无需大量标注数据的情况下,结合物理定律约束进行偏微分方程的数值求解。该方法将神经网络与物理方程深度融合,适用于复杂波动问题的建模与仿真,并提供了完整的Matlab实现方案,便于科研人员理解和复现。此外,文档还列举了多个相关科研方向和技术服务内容,涵盖智能优化算法、机器学习、信号处理、电力系统等多个领域,突出其在科研仿真中的广泛应用价值。; 适合人群:具备一定数学建模基础和Matlab编程能力的研究生、科研人员及工程技术人员,尤其适合从事计算物理、声学仿真、偏微分方程数值解等相关领域的研究人员; 使用场景及目标:①学习并掌握PINN在求解三维声波波动方程中的应用原理与实现方式;②拓展至其他物理系统的建模与仿真,如电磁场、热传导、流体力学等问题;③为科研项目提供可复用的代码框架和技术支持参考; 阅读建议:建议读者结合文中提供的网盘资源下载完整代码,按照目录顺序逐步学习,重点关注PINN网络结构设计、损失函数构建及物理边界条件的嵌入方法,同时可借鉴其他案例提升综合仿真能力。
"GLThread 102" prio=5 tid=57 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x23b23f8 self=0xb400007afa771000 | sysTid=10035 nice=0 cgrp=foreground sched=0/0 handle=0x7c2cf49730 | state=R schedstat=( 2694792821 5252161613 1877 ) utm=251 stm=17 core=6 HZ=100 | stack=0x7c2ce46000-0x7c2ce48000 stackSize=1037KB | held mutexes= native: #00 pc 017b4680 /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #01 pc 017b4540 /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #02 pc 0169f304 /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #03 pc 008089a0 /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #04 pc 00800b2c /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #05 pc 00722e68 /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #06 pc 0071d37c /vendor/lib64/egl/mt6789/libGLES_mali.so (???) (BuildId: 904ca932166721ad) native: #07 pc 03551464 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #08 pc 03551108 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #09 pc 032ca0c4 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #10 pc 032ce014 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #11 pc 02da5710 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #12 pc 02da0720 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #13 pc 02da0864 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #14 pc 02db3bac /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #15 pc 02db4078 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #16 pc 02d074d0 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #17 pc 02d0679c /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #18 pc 02d065d8 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #19 pc 02cbfc50 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #20 pc 02cbf974 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #21 pc 02caa4b8 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #22 pc 02caa420 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #23 pc 033ae9f0 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (???) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) native: #24 pc 033b7e88 /data/app/~~hLUA-ia9OCk-zxfDyOZ4lw==/com.king.candycrushsodasaga-QMh9M_-uCpVSrP1UiJaaiw==/lib/arm64/libstritz.so (Java_com_king_core_NativeApplication_step+36) (BuildId: b3eec629d5da5b02d0fee387bab093b87339f101) at com.king.core.NativeApplication.step(Native method) at com.king.core.GameRenderer.onDrawFrame(GameRenderer.java:129) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1634) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1284)挂哪里
08-05
在 Android 开发中,`GLSurfaceView` 是一个用于 OpenGL 渲染的视图组件,其内部通过 `GLThread` 管理渲染线程。当开发者在使用 `GLSurfaceView` 时遇到 `GLThread` 挂起或崩溃问题,通常与生命周期管理、线程同步、资源释放等环节密切相关。 ### GLThread 挂起的可能原因 1. **生命周期状态管理不当** `GLSurfaceView` 的 `GLThread` 依赖于其生命周期方法(如 `surfaceCreated`、`surfaceChanged` 和 `surfaceDestroyed`)来控制渲染线程的启动与停止。如果这些方法未被正确调用,或者调用顺序混乱,可能导致 `GLThread` 进入等待状态而无法继续执行。例如,在 `surfaceDestroyed` 中未正确通知线程退出,会导致线程卡在等待状态[^2]。 2. **线程同步问题** `GLThread` 是一个独立的渲染线程,与主线程之间存在交互。如果在主线程中执行某些阻塞操作,或者在渲染线程中访问未同步的资源,可能导致死锁或线程挂起。例如,在渲染线程中调用 `requestRender()` 时,若主线程正在等待渲染线程完成某些操作,则可能造成相互等待。 3. **Native 层资源释放不及时** 如果在 `onPause()` 或 `onDestroy()` 中未能正确释放 OpenGL 资源,可能导致 Native 层仍持有某些对象引用,进而影响 `GLThread` 的正常退出。这通常表现为线程在等待资源释放时挂起。 4. **Surface 被销毁后仍尝试操作** 当 `GLSurfaceView` 的 `Surface` 被销毁后,如果 `GLThread` 仍在尝试调用 `surfaceCreated()` 或其他与 `Surface` 相关的方法,将导致 `NullPointerException` 或其他异常,进而引发崩溃或挂起[^2]。 ### NativeApplication step 方法崩溃分析 在使用某些基于 OpenGL 的游戏引擎(如 LibGDX)时,`NativeApplication` 的 `step()` 方法用于驱动主循环。如果在此方法中发生崩溃,常见原因包括: 1. **JNI 调用异常** `step()` 方法内部通常会调用 Native 层的函数。如果 Native 层出现异常(如空指针、数组越界等),会导致 JVM 抛出 `JNIException`,进而引发崩溃。 2. **OpenGL 上下文丢失** 如果在 `step()` 中执行 OpenGL 操作时上下文已丢失(例如在 `surfaceDestroyed` 后仍尝试绘制),将导致非法操作,从而引发崩溃。 3. **资源未正确初始化** 在 Native 层初始化未完成时调用 `step()`,可能导致访问未初始化的对象,从而引发崩溃。 4. **线程竞争或死锁** 如果 `step()` 方法涉及多线程操作且未正确处理同步问题,可能造成死锁或资源竞争,最终导致崩溃。 ### 建议解决方案 - **确保生命周期回调正确执行** 在 `onResume()` 和 `onPause()` 中调用 `GLSurfaceView.onResume()` 和 `GLSurfaceView.onPause()`,以确保渲染线程正确启动与停止。 - **避免跨线程访问共享资源** 在渲染线程和主线程之间访问共享资源时,使用同步机制(如 `synchronized` 或 `Handler`)进行保护。 - **及时释放 Native 资源** 在 `onDestroy()` 中确保释放所有 OpenGL 资源,并通知渲染线程停止。 - **捕获并处理异常** 在 Native 层和 Java 层添加异常捕获机制,防止因未处理异常导致程序崩溃。 ### 示例:确保 GLSurfaceView 生命周期正确调用 ```java public class MyGLActivity extends AppCompatActivity { private GLSurfaceView glSurfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); glSurfaceView = new GLSurfaceView(this); glSurfaceView.setRenderer(new MyGLRenderer()); setContentView(glSurfaceView); } @Override protected void onResume() { super.onResume(); glSurfaceView.onResume(); // 正确启动渲染线程 } @Override protected void onPause() { super.onPause(); glSurfaceView.onPause(); // 正确暂停渲染线程 } } ``` ### 示例:避免在 Surface 销毁后继续操作 ```java public class MyGLRenderer implements GLSurfaceView.Renderer { private boolean surfaceCreated = false; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { surfaceCreated = true; // 初始化 OpenGL 资源 } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { if (!surfaceCreated) return; // 更新视口 } @Override public void onDrawFrame(GL10 gl) { if (!surfaceCreated) return; // 绘制逻辑 } public void releaseResources() { surfaceCreated = false; // 释放资源 } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值