JVM类加载机制_字节码执行引擎_Java内存模型

类加载机制:

类加载生命期:加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using),卸载(Unloading)初始化:1.遇到new,getstatic,putstatic,invokestatic指令,类没有进行初始化,先触发初始化2.java反射机制3.初始化一个类,父类没有初始化,需要先触发父类的初始化4.JVM启动的时候,用户需要指定一个执行的主类(main所在的位置),JVM优先初始化5.JDK1.7动态语言支持注:1.只有直接定义静态字段(static int i=1;)的类才会被初始化,而(static{sysout("Hello")})并不会触发初始化2.类在初始化的时候必须要求其父类初始化,但是接口不需要,只有真正使用到父类接口,父类接口才会初始化加载:1.通过一个类的全限定名来获取定义此类的二进制字节流//因此可从jar,war,网络获取类结构2.将这个字节流所代表的静态结构转化为方法区的运行时数据结构3.在内存中生成一个代表这个类的java.lang.Class对象,作为方法区的访问入口注:类加载的过程可以通过系统的类加载器来完成,也可以自定义类加载器控制字节流获取方式加载阶段完成之后,类的字节流文件按照JVM的格式(格式由JVM定)储存在方法区中,然后在内存中实例化一个java.lang.Class对象对于HotSpot来说,该对象存放在方法区中,这个对象将作为程序访问的方法区数据类型的接口验证:确保Class文件的字节流中包含的信息不会损害JVM1.格式验证:是否以魔数开头,主次版本号,常量池中是否有不支持常量的类型,编码情况,Class文件是否具有附加信息.....2.元数据验证:检查是否符合Java语言规范3.字节码验证:验证类型转换4.符号引用验证:字符串限定符,类字段,方法的限定符准备:为类变量(静态变量)分配内存,设置初值(默认0/false/null),实例变量的初始化跟随对象一起分配到Java堆中解析:将符号引用(通过一组符号描述引用目标,符号引用的实现与内存布局无关)替换为直接引用(直接指向目标的指针/句柄)解析动作主要针对类或接口,字段,类方法,接口方法,方法类型,方法句柄,和调用限定符7类符号引用进行,分别对应常量池的CONSTANT_Class_info,CONSTANT_Fieldref_info,CONSTANT_Methodref_info,CONSTANT_InterfaceMethodref_info,CONSTANT_MethodType_info,CONSTANT_MethodHandle_info和CONSTANT_InvokeDynamic_info 7中类型字段解析,类方法解析,接口方法解析初始化(类加载过程最后一步//初始化阶段的过程就是执行类构造器<climit>()方法的过程):<climit>()方法是由编译器自动收集类中所有变量的赋值动作和静态语句块(static{}块)中的语句合并产生,编译器收集的顺序是由语句在源文件中出现顺序决定例:public class Test {static{i = 0;//静态代码块中的i可以被赋值,但不能被访问(非法向前引用)正常编译System.out.println(i);//报 illegal forward reference(非法向前引用)}static int i = 1;//如果要访问i,应该将i在静态代码块前面进行声明}<climit>()方法与类的构造方法(<init>()方法)不同,它不需要显示地调用父类构造器,虚拟机保证在子类的<climit>()方法执行之前,父类的<climit>()方法已经执行完毕,因此在JVM中第一个被执行的<climit>()方法的类肯定是java.lang.Object由于<climit>()先执行,所以静态语句块优先加载例:static class parent{public static int a=1;static{a=2;}}static class sub extends parent{public static int b=a;//此时b会被初始化为2}注:<climit>()对于类或接口来说,不是必须的,当类中没有静态语句块,没有对类变量赋值操作,编译器将不会生成<climit>方法接口中不能使用静态语句块,但可以有变量赋值操作,说明接口和类都一样会生成<climit>(),接口与类不同的是,接口中不需要先执行父类的<climit>(),只有使用父接口才会去初始化JVM会保证一个类的<climit>()在多线程的环境中被正确加锁,同步,多个线程同时初始化一个类,将只会有一个线程去执行类的<climit>(),其他线程阻塞,直到线程活动执行完<climit>()完毕,就此会造成线程阻塞问题(并且很隐蔽)类加载器双亲委派模型前序:启动类加载器(Bootstrap ClassLoader)//C++语言实现,JVM自身一部分,主要作用是将放在<JAVA_HOME>\lib目录中/被-Xbootclasspath参数指定的路径的类库(要被JVM识别)加载到JVM内存中扩展类加载器(Extension ClassLoader):由sun.misc.Launcher$ExtClassLoader实现,用于加载<JAVA_HOME>\lib\ext目录中/java.ext.dirs系统变量所指定的路径中所有类库应用程序加载器:加载用户类路径上指定类库最后加载器为自定义加载器上述加载器除Bootstrap ClassLoader统称为其他类加载器//由java语言实现,独立于虚拟机外部,继承于抽象类java.lang.ClassLoader双亲委派模型(强制性约束模型):一个类收到加载请求首先会委派父类加载器完成,直到请求传送到顶层启动类加载器中,只有当父类反馈无法完成加载请求,子类加载器才会尝试加载,保证程序的稳定运行OSGi环境下,类加载器不再是树状模型,而是网状,他会采用同级之间的类进行加载

字节码执行引擎

执行引擎:使用解释器执行,通过及时编译器产生本地代码执行
运行栈帧结构:
栈帧:支持虚拟机进行方法调用和方法执行的数据结构
栈帧储存的东西:方法的局部变量表:存放参数和方法内部定义的局部变量,编译Class文件,在方法的Code属性的max_locals确定了局部变量表的最大内容方法执行的过程,JVM使用局部变量完成参数值到参数变量列表的传递过程非静态方法,局部变量表中第0个索引的slot默认适用于传递方法所属的对象实例的引用(this),其余参数按照参数表的顺序排列//为节省空间,slot可以重用slot(Variable Slot,变量槽):局部变量表容量的最小单位(未说明具体占用空间大小),每个slot都可以存放一个boolean,byte,char,short,int,float,reference,returnAddress类型数据一个slot可以存放32位以内的数据类型reference表示对对象数据的引用:可以通过此引用直接或间接地查找到对象所属数据类型在方法区中的储存类型信息64位的数据类型,虚拟机会以最高位对齐的方式为其分配两个连续的slot空间Java中64位数据(reference可能是32位,也可能是64位)的只有long和double, JVM通过索引定位的方式使用局部变量表,索引范围从0开始,64位数据,则会同时使用n,n+1两个slotSlot重用:当方法体中的变量作用域未覆盖整个方法体,且pc计数器超出这个变量的作用域范围,为节省空间,Slot将会复用,但是复用也会影响到GC(当发现solt没有被其他其他变量复用,GC Roots还保持这引用之间的关联,那么,即使离开了变量的作用域范围,GC却不会回收内存),所以不使用的变量要手动设置null,避免GC错误注:局部变量必须赋初值,于类变量不一样操作数栈(操作栈):在编译时确定了栈最大深度,在方法的Code属性的max_stacks确定(栈深度永远不会超出该深度)操作数栈的每一个元素可以是任意数据类型,包含long/double32位所占的栈容量为1,64位为2动态链接:方法返回地址:在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行, 方法推出的过程,实际上就是等于把当前栈出栈,因此退出时的操作:恢复上层方法的局部变量表和操作数栈,把返回值压入调用者栈帧的操作数栈中,调整PC计数器的值以指向调用指令后面的一条指令方法退出的方式:正常完成出口:调用者的PC计数器的值可以作为返回地址,栈帧中会保留这个计数器的值异常出口:返回值需要通过异常处理器来确定,栈帧中一般不会保留此消息注:方法重载是静态分派的典型应用(编译时确定对象),方法重写是动态分派的典型应用(运行时确定对象)方法调用:Class文件不包含传统编译的连接操作,一切方法调用直接是调用在Class文件的符号引用,而非方法实际运行时的内存布局的入口地址1.解析:类加载解析阶段,将其中一部分符号引用转化为直接引用,符合编译期可知,运行期不变---静态方法,私有方法(二者的隐蔽性,不能被重写,即不可实现多态)JVM内置方法调用字节码指令:invokestatic:调用静态方法;invokespecial:调用实例构造器<init>方法,私有方法,父类方法;invokevirtual:调用所有虚方法invokeinterface:调用接口方法,运行时确定实现接口的对象(分派逻辑由用户设定引导)invokedynamic:运行时动态解析调用出限定符所引用的方法注: invokestatic,invokespecial一定是调用静态/私有/构造/父类方法,类加载的时候就会将符号引用转化为直接引用(上述方法为非虚方法, 除上述方法,final方法其余方法都为虚方法),final方法不能被覆盖,就没有多态的说法2.分派:静分派:在编译时就确定引用所指的对象; 典型应用就是重载动态分派:与多态相关---重写3.JVM动态分派的实现:建立虚表结构:当子类没有对父类的方法进行重写是,子类虚方法表里的入口地址和父类的入口地址一致,如果子类重写父类方法,子类方法表中的地址将会替换为子类重写后方法的入口地址4.java.lang.invoke:java中不能将函数名作为参数(函数指针),只能通过;当Method Handle提出后,就可以将函数名作为参数JDK1.7提供的动态确定目标方法机制:MethodHandle;MethodHandle与反射的区别:反射实在java代码级别模拟方法调用,MethodHandle是在字节码级别MethodHandle的一部分方法对应的字节码指令执行的权限校验行为,Reflection API中无需关心Reflection是为Java语言服务,MethodHandle可以设计为服务于所有的JVM,当然也包含Java语言invokedynamic指令(静态解析--解析私有方法,静态方法两大类)每一处含有invokedymic指令的位置称作是动态调用点(Dynamic Call Site),这条指令的第一个参数不再是代表方法符号引用的CONSTANT_Methodref_info常量,而是CONSTANT_MEthodrefDynamic_info常量,该常量中可以得到:Bootsrap method引导方法,有固定的参数,返回值为java.lang.invoke.CallSite,代表真正要执行的方法调用; Method Type(方法类型);方法名称静态分派--方法重载的过程中调用重载,形参会根据语义选择合适的方法动态分派--多态性体现(重写):由于invokevirtual在运行时确定接受者不同的类型,然后会将常量池中类方法符号解析到不同的直接引用上面,invokevirtual搜索接收者的方法时通过虚方法表(如果子类重写父类方法,表中的函数入口优先指向子类的方法,反之指向父类,接口也一致)

Java内存模型:

主内存:Java内存模型规定所有的变量都保存在主内存中工作内存:每个线程都有自己的工作内存,保存了该线程使用到的变量的主内存副本拷贝主内存与工作内存的关系:线程对变量的所有操作都必须在自己的工作内存中进行,不能直接读写主内存中的变量不同线程之间无法直接访问对方工作内存中的变量线程间变量值的传递均需要通过主内存来完成内存交互操作(变量与主内存中间的操作,下列操作都是原子性):lock:将变量标识为一条线程独占状态,作用于主内存的变量unlock:将锁定状态的变量释放,释放后的变量才可以被其他线程锁定read:将变量值从主内存传输到线程的工作内存中load:作用于工作内存将读取后的变量放入工作内存的副本中use:将工作内存中的变量传递给执行引擎,每当JVM遇到一个需要使用的变量值的字节码指令就会执行这个操作assign(赋值):将一个执行引擎接收到的值赋给工作内存的变量,每JVM遇到变量赋值的字节码指令执行这个操作//作用于工作内存store(储存):将工作内存中的一个变量值传送到主内存中,以便write使用//作用于工作内存write:将store操作送过来的变量放入主内存的变量中注:read-load,store-write必须顺序执行,不需要连续执行(read a,read a,load b,load b),不可单独出现不允许一个线程丢弃它最近的assign的操作,即变量在工作内存中改变了之后必须把该变化同步到主内存中不允许一个线程无原因地把数据从线程的工作内存同步回主内存中一个新变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化的变量一个变量在同一时刻只允许一条线程对其lock操作,但lock操作可以被同一条线程执行多次,多次执行lock后,只有执行相同次数的unclock,变量才能解锁如果对一个变量执行lock操作,将会清空工作内存 中此变量的值,在执行引擎使用这个变量前,需要重新执行load/assign来初始化变量如果一个变量没被lock锁定,则不允许对它执行unclock,unclock也一致对变量执行unclock操作之前,必须把此变量同步到主内存中(执行store/write)volatile(最轻量级同步机制)变量被声明为volatile,具有以下特性:(1) 保证可见性,不保证原子性a.当写一个volatile变量时,JMM会把该线程本地内存中的变量强制刷新到主内存中去;b.这个写会操作会导致其他线程中的缓存无效。(2)禁止指令重排 重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。重排序需要遵守一定规则:a.重排序操作不会对存在数据依赖关系的操作进行重排序。比如:a=1;b=a; 这个指令序列,由于第二个操作依赖于第一个操作,所以在编译时和处理器运行时这两个操作不会被重排序。b.重排序是为了优化性能,但是不管怎么重排序,单线程下程序的执行结果不能被改变比如:a=1;b=2;c=a+b这三个操作,第一步(a=1)和第二步(b=2)由于不存在数据依赖关系, 所以可能会发生重排序,但是c=a+b这个操作是不会被重排序的,因为需要保证最终的结果一定是c=a+b=3。(3) 使用volatile关键字修饰共享变量便可以禁止这种重排序。若用volatile修饰共享变量,在编译时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序,volatile禁止指令重排序也有一些规则:a.当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;b.在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。即执行到volatile变量时,其前面的所有语句都执行完,后面所有语句都未执行。且前面语句的结果对volatile变量及其后面语句可见。重排序在单线程下一定能保证结果的正确性,但是在多线程环境下,可能发生重排序,影响结果,下例中的1和2由于不存在数据依赖关系,则有可能会被重排序,先执行status=true再执行a=2。而此时线程B会顺利到达4处,而线程A中a=2这个操作还未被执行,所以b=a+1的结果也有可能依然等于2。加volatile后,变量会生成内存屏障(即lock锁住变量):I.它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;II. 它会强制将对缓存的修改操作立即写入主存;III. 如果是写操作,它会导致其他CPU中对应的缓存行无效。//保证此变量对所有线程的可见性,当一条线程修改了这个变量的值,其他线程也会知道,Java的运算并非原子操作,导致volatile变量的运算在并发下是不安全的,即volatile只能保证可见性,所以通常还是需要synchronized/java.util.concurrent中的原子来保证原子性注:long double 64位数据不具有原子性,但是jvm为其读写操作进行了原子性处理,无需为long double 添加volatile
原子性:定义: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。Java中的原子性操作包括:a. 基本类型的读取和赋值操作,且赋值必须是数字赋值给变量,变量之间的相互赋值不是原子性操作。b.所有引用reference的赋值操作c.java.concurrent.Atomic.* 包中所有类的一切操作
可见性:定义:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。在多线程环境下,一个线程对共享变量的操作对其他线程是不可见的。Java提供了volatile来保证可见性,当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,其他线程读取共享变量时,会直接从主内存中读取。当然,synchronize和Lock都可以保证可见性。synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
有序性:定义:即程序执行的顺序按照代码的先后顺序执行。synchronized:保证可见性,对一个变量执行unclock之前,必须先把此变量同步回主内存中final:被final修饰的变量在构造器中初始化完成,但构造器没有把this的引用传递出去,在其他线程中可以看见final字段的值有序性:在当前线程内,所有的操作都是有序的,但从当前线程中观察另一个线程,所有的操作都是无序的JVM的线程实现基于操作系统,windows,linux使用一对一的线程模型; 线程调度模式使用抢占式,自动完成程序次序规则:一个线程内,按照代码顺序(控制流顺序及逻辑顺序),前面的代码比后面的代码先行发生管理锁定规则:一个unclock操作先行发生于后面对于同一个锁的lock操作volatile变量规则:对于一个volatile变量的写操作先行发生于后面对这个变量的读操作//先write进主内存,另一线程再read进工作内存线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作线程终止规则:线程中所有操作都先行发生于对此线程的终止检测,通过Thread.join()方法结束,Thread().isAlive的返回值手段检测线程已经终止执行线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断时间的发生,可以通过Thread.interrupt()方法检测是否有中断发生对象终结规则:一个对象的初始化完成先行发生于它的finalize()的开始传递性:如果操作A先行发生于操作B,操作B先行发生于操作C,说明操作A先行发生于操作C解决线程安全:1.互斥同步:阻塞式同步;保证共享数据同一时刻只能被一条线程使用,使用重量级synchronize操作,在对线程状态唤醒,睡眠需要到内核中进行, 导致状态转移操作的时间比代码一般时间较长; 使用ReentrantLock实现同步,相比于synchronize他多增加: 线程等待锁时间过长自动中断,多个线程等待同一个锁,获得锁的顺序按照申请锁的顺序而定,可以锁住多个条件; 但是在性能上还是使用synchronize2.非阻塞式同步: 共享数据发生冲突,不需要将线程挂起,而是采取补偿措施,对修改的数据进行修正3.可重入代码: 执行线程中判断执行结果是否满足预期,不满足执行其他代码4.线程本地储存:消费者-工厂模式, 阻塞队列5.锁优化:自旋锁: 让线程执行忙循环,不让线程挂起(线程切换很浪费资源,自旋不等价于阻塞),该线程不断检查锁是否释放所占用时间短的时候,自旋效果好,当锁占用时间过长,自旋效果不好自适应自旋:根据上一个自旋过程时间决定自旋次数以及是否自旋6.锁消除:当堆上数据不会出现逃逸,那么直接会将该数据当做栈上数据,同步锁自动消除例:public String f(String s1, String s2){//代码反编译之后等价于s1.append(s2), 由于s1,s2不会逃逸到f外部,所以s1,s2连接的时候自动消除append的同步操作机制return s1+s2;}7.锁粗化:使同步模块控制的范围扩大, 就比如在for外部加锁,而不是for内部,重复加锁,消锁也会导致性能损失8.轻量级锁:传统锁(重量级锁),轻量级锁用于减少重量级锁使用操作系统互斥量产生的性能消耗9.偏向锁:在数据无竞争的时候直接消除CAS,偏向锁会偏向于第一个获得他的线程,在接下来的执行的过程中,该锁没有被其他线程获取,则持有偏向锁的线程永远不需要同步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新车载导航端口检测工具_高德地图这个功能 把微信都没做好的车载社交解决了?...

在汽车网联化和智能化带给人们的诸多想象里&#xff0c;车内社交似乎是最虚无缥缈的那个。在移动互联网领域&#xff0c;微信通过满足人们社交需求这个基本点&#xff0c;构建起庞大的用户群体&#xff0c;展示出巨大的市场前景。但在驾车场景下&#xff0c;车载社交该怎么玩&a…

王译潇20162314 第九周作业总结

学号 20162314 2016-2017-2 《Java程序设计》第九周学习总结 教材学习内容总结 数据库是为其他程序提供数据的应用软件 关系数据库通过唯一的标识符在不同表的记录间建立了关系 JDBC API用来建立到数据库的连接 CREATE TABLE SQL 语句用来创建新的数据库表 ALTER TABLE SQL 语句…

sketchup边线设置_春天花花天桥,SketchUp草图大师快速建模!

最近小吧在网上看到一座设计很特别的天桥&#xff0c;形状很像一朵花&#xff0c;名字也十分写实——春花天桥。喏&#xff0c;就是下面这个家伙&#xff01;图片来自网络春花天桥是2011年深圳举办大运会前夕投资建设的形象提升工程之一&#xff0c;在建设初期就被定位为地标性…

自言自语

随笔, 自我审视, 需要反思 最近这段时间, 各种艰难困苦早已将最初的激情冲刷地只剩下骨头了, 每天拖着疲惫的身子, 总是做着没有意义的事; 迷失了自我, 总把时间浪费, 而在做浪费时间的事却没有思考做这件事是否是有意义的, 是否是有价值的, 是否是在浪费时间; 没有思考, 就像行…

忧愁无处发

顶着好多方面的压力回家了....过得不好。。。。转载于:https://www.cnblogs.com/ysw6/p/6789910.html

python求直角三角形第三边公式_直角三角形已知两边求第三边公式

展开全部解&#xff1a;分两种情况讨论1、需要求的第三边为斜边时&#xff0c;第e69da5e887aa3231313335323631343130323136353331333433643030三边长度√a^2b^2 (ab分别为两直角边的长度)2、需要求的第三边为直角边时,第三边长度√c^2-a^2 (其中c为斜边,a为已知直角边)扩展资料…

android 7.1 apk的systemuid和系统应用Setting相同导致开机找不到库的问题

1、前言Android apk加载机制这就是我最近在解决的一个问题&#xff0c;32位的apk可以用32位的库&#xff0c;那64位的apk可以用64位的库&#xff0c;如果我想64位的apk同时使用32和64位的库呢&#xff1f;android加载so文件的机制apk在安装的过程中&#xff0c;系统就会对apk进…

Struts2_1_基础案例_配置文件详解_动作类

Struts2简要概述 三层架构中的表现层框架相对于常规的MVC模式, 其核心为Filter控制器内部的Filter实例是在客户端每发送一次就实例化一次, 相比于Servlet具有线程安全性内部控制器默认拦截以.action或无后缀名的url Struts2案例步骤 配置web.xml, 由于Struts2核心为Fiter, 所…

BZOJ 3362 Navigation Nightmare 带权并查集

题目大意&#xff1a;给定一些点之间的位置关系&#xff0c;求两个点之间的曼哈顿距离 此题土豪题。只是POJ也有一道相同的题&#xff0c;能够刷一下 别被题目坑到了&#xff0c;这题不强制在线。把询问离线处理就可以 然后就是带权并查集的问题了。。。将权值设为方向向量&…

怎样的人适合当码农?

1高中的时候&#xff0c;我一个友仔&#xff0c;他说要创办一个科技协会&#xff0c;然后跟我说电脑里面的代码都是0和1组成的&#xff0c;我现在还记得那天我们在学校开会的时候讨论电脑如何运行&#xff0c;我一脸痴呆的听他给我讲解电子知识&#xff0c;而且他后面自己做了一…

Struts2_2_解决配置文件冗余_动作类对象数据封装_数据类型转换_表单数据信息提示

Struts2第二天学习 解决struts.xml文件的冗余 将所有的配置文件放在一份struts.xml将会导致, 文件繁杂且容易出错, 将有如下的解决方案: 分文件编写Struts2的配置文件:对于具有类似功能的action就可以放入不同对应的xml文件中, 最后使用struts标签中的<include file"…

高版本号chrome安装flashplayer debuger后无法使用的问题

起因应该是苹果公司指出flash player的安全问题&#xff0c;还有各种原因导致google将在未来取消NPAPI的支持&#xff0c;所以fp们就悲剧了在高版本号chrome&#xff08;42以上&#xff09;默认是关闭外部安装的插件使用的&#xff0c; 所以在地址栏通过chrome://flags/#enable…

android 7.1 apk的systemuid [2]

1 上周发的一篇文章《android 7.1 apk的systemuid和系统应用Setting相同导致开机找不到库的问题》&#xff0c;然后有个小伙伴找我讨论了&#xff0c;觉得自己的脑洞了打开了很多&#xff0c;所以针对这个问题再次做一次总结&#xff0c;如果大家有好的建议也可以在文末留言。…

python连连看小游戏_python实现连连看游戏

编程一直是在课余时间&#xff0c;放假时间自学&#xff0c;到现在为止也有半年了。这是我自己用python实现的连连看&#xff0c;也是第一个完成的游戏&#xff0c;虽然极其简陋。思路呢&#xff0c;一开始是想要从一个点出发开始寻路&#xff0c;遇到数字就换一条路&#xff0…

Struts2_3_国际化处理_自定义拦截器_文件上传及下载_OGNL

Struts2国际化处理 浏览器根据当前的语言环境自动查找对应的语言环境资源包, 使jsp显示合适的语言数据环境 Struts2实现国际化, 动作类必须继承ActionSupport 创建资源包 资源包由多个properties文件组成, properties文件的文件名必须满足命名规范: 文件名_语言代码_国家代码…

RBAC 基于角色的访问控制

RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;&#xff0c;就是用户通过角色与权限进行关联。简单地说&#xff0c;一个用户拥有若干角色&#xff0c;每一个角色拥有若干权限。这样&#xff0c;就构造成“用户-角色-权限”的授权模型。…

C语言书籍大全

学习过linux的同学应该都知道&#xff0c;linux系统几乎都是用c编写&#xff0c;包括现在主流的android,ios系统&#xff0c;都是使用c编程。为了方便大家学习C语言&#xff0c;小编搜集整理了市面几乎所有的C语言书籍&#xff0c;下面给出部分比较有名的&#xff0c;在微信公众…

python子进程修改父进程内变量_如何将父变量传递给python中的子进程?

这里的简单答案是&#xff1a;不要使用subprocess.Popen,使用multiprocessing.Process.或者,更好的是,multiprocessing.Pool或concurrent.futures.ProcessPoolExecutor.使用子进程,程序的Python解释器根本不了解子进程;据它所知,子进程正在运行Doom.所以没有办法直接与它共享信…

设计模式_1_工厂模式与抽象工厂

工厂模式 工厂模式(创建型模式):创建对象接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建延伸到子类进行 主要解决接口选择问题,明确计划不同条件下执行创建不同实例 通过子类实现工厂实例,创建过程在其子类执行 优点:提高扩展性,屏蔽产品具体实现,调用者只关心产品…

android 7.1 apk的systemuid相同导致问题[2]

1上周发的一篇文章《android 7.1 apk的systemuid和系统应用Setting相同导致开机找不到库的问题》&#xff0c;然后有个小伙伴找我讨论了&#xff0c;觉得自己的脑洞了打开了很多&#xff0c;所以针对这个问题再次做一次总结&#xff0c;如果大家有好的建议也可以在文末留言。2先…