VR虚拟现实java虚拟机.docx
《VR虚拟现实java虚拟机.docx》由会员分享,可在线阅读,更多相关《VR虚拟现实java虚拟机.docx(39页珍藏版)》请在冰点文库上搜索。
VR虚拟现实java虚拟机
Java摆脱了硬件平台的束缚,实现了“一次编写,到处运行”的理想;它提供了一种相对安全的内存管理和访问机制,避免了绝大部分的内存泄露和指针越界问题;它实现了热点代码检测和运行时编译及优化,这使得java应用能随着运行时间的增加而获得更高的性能。
JDK:
java程序设计语言、java虚拟机、javaAPI类库。
JavaAPI类库中的javaSEAPI子集和java虚拟机这两部分统称为JRE。
Java技术关注的重点业务领域划分:
1.javaCard:
支持一些java小程序运行在小内存设备上的平台。
2.JavaME:
支持java程序运行在移动终端上的平台。
3.JavaSE:
支持面向桌面级应用的java平台。
4.JavaEE:
支持使用多层架构的企业应用。
运行时数据区:
1.程序计数器:
一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。
Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的。
此内存区域是唯一一个在java虚拟机规范中没有规定任何outofmemoryerror情况的区域。
2.Java虚拟机栈:
是线程私有的。
它的生命周期与线程相同。
虚拟机描述的是java方法执行的内存模型:
每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。
每一个方法被调用直至执行完成的过程,就对应于一个栈帧在虚拟机栈中从入栈到出栈的过程。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出stackoverflowerror异常;如果虚拟机可以动态扩展,当扩展时无法申请到足够的内存时会抛出outofmemoryerror异常
3.本地方法栈:
与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则是为虚拟机使用到的native方法服务。
4.Java堆:
java堆是被所有线程共享的一块内存区域。
用来存放对象实例。
是垃圾收集器管理的主要区域。
现在收集器基本上都是采用的分代收集算法。
5.方法区:
是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。
运行时常量池:
是方法区的一部分。
用于存放编译期生成的各种字面量和符号引用。
如果使用直接指针访问方式,java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。
如果是内存泄漏,可进一步通过工具查看泄漏对象到GCRoots的引用链。
掌握了泄漏对象的类型信息,以及GCRoots引用链的信息,就可以比较准确的定位出泄漏代码的位置。
不存在泄漏,那么应当检查虚拟机的堆参数,与机器物理内存对比看是否可以调大。
为什么要了解GC和内存分配:
当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。
我们只有在程序处于运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存。
引用计数算法:
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器就减1;任何时刻计数器都为0的对象就是不可能再被使用的。
有个例子:
objA和objB都有字段instance,赋值令objA.istance=objB及objB.instance=objA。
除此之外,这两个对象再无任何引用,实际上这两个对象已经不可能再被访问,但是他们因为互相引用着对方,导致它们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收他它们。
System.gc()。
虚拟机并没有因为这两个对象互相引用就不回收它们。
说明虚拟机并不是通过引用计数算法判断对象是否存活。
根搜索算法:
通过一系列的名为“GCRoots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连时,则证明此对象是不可用的。
GCRoots的对象包括下面几种:
虚拟机栈中的引用的对象;方法区中的类静态属性引用的对象;方法区中的常量引用的对象;本地方法栈中JNI的引用的对象。
对象回收:
首先对象在进行跟搜索后发现没有与GCRoots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()的方法。
当对象没有覆盖finalize()方法或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。
如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会被放置在一个名为F-Queue的队列中,并在稍后由一条有虚拟机自动建立的、低优先级的finalizer线程去执行。
这时,在进行第二次小规模的标记,如果此时有对象重新与引用链的任何一个对象建立关联,那么就被移除出“即将回收”的集合。
剩下的,就等着回收。
垃圾收集算法:
1.最基础的收集算法是“标记-清除”算法:
首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
缺点:
效率不高;会产生大量不连续的内存碎片。
2.复制算法。
将内存容量划分为大小的两块。
每次只使用其中的一块。
当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
3.标记-整理算法:
标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
4.分代收集算法:
根据对象的存活周期的不同将内存划分为几块。
一般是把java堆分为新生代和老生代,这样就可以根据各个年代的特点采用最适当的收集算法。
在新生代中,每次垃圾收集时发现大批对象死去,只有少量存活,那么选用复制算法。
在老生代中,对象存活率高,没有额外的空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。
23种设计模式:
1.抽象工厂模式:
他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。
在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。
所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
2.工厂方法模式:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
优点:
可以使代码结构清晰,有效地封装变化;对调用者屏蔽具体的产品类;降低耦合度。
3.单例模式:
单例模式有一下特点:
1、单例类只能有一个实例。
2、单例类必须自己自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。
这些应用都或多或少具有资源管理器的功能。
Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。
由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。
4.代理模式:
代理模式:
给某一对象提供代理对象,并由代理对象控制具体对象的引用.
代理模式涉及的角色:
1:
抽象主题角色.声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替.
2:
代理主题角色.含有真实主题的引用,从而可以在任何时候操作真实主题,代理主题功过提供和真实主题相同的接口,使它可以随时代替真实主题.代理主题通过持有真实主题的引用,不但可以控制真实主题的创建或删除,可以在真实主题被调用前进行拦截,或在调用后进行某些操作.
3:
真实代理对象.定义了代理角色所代表的具体对象.
java对代理模式的支持---动态代理
上面的代理,我们强迫代理类RedWineProxy实现了抽象接口SellInterface.这导致我们的代理类无法通用于其他接口,所以不得不为每一个接口实现一个代理类.幸好,java为代理模式提供了支持.
java主要是通过Proxy类和InvocationHandler接口来给实现对代理模式的支持的.
通过上面的代码可以看出,代理主题ProxyObject类并没有实现我们定义的SellInterface借口,
而是实现了java的InvocationHandler接口,这样就把代理主题角色和我们的业务代码分离开是实现了java的InvocationHandler接口,这样就把代理主题角色和我们的业务代码分离开来,使代理对象能通用于其他接口.其实InvocationHandler接口就是一种拦截机制,当系统中有了代理对象以后,对原对象(真实主题)方法的调用,都会转由InvocationHandler接口来处理,并把方法信息以参数的形式传递给invoke方法,这样,我们就可以在invoke方法中拦截原对象的调用,并通过反射机制来动态调用原对象的方法来,使代理对象能通用于其他接口.
5.责任链模式:
责任链模式是一种对象的行为模式。
在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
请求在这个链上传递,直到链上的某一个对象决定处理此请求。
发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
6.观察者模式:
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对象,让他们能够自动更新自己。
观察者模式的组成:
1.抽象主题角色
2.抽象观察者角色:
3.具体主题角色(Watched):
把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。
抽象主题提供一个接口,可以增加和删除观察者角色。
一般用一个抽象类或接口来实现。
4.具体观察者角色(Watcher):
为所有具体的观察者定义一个接口,得到主题的通知时更新自己
1.抽象主题角色类
2.抽象观察者角色
3.具体主题角色(Watched)
4.具体观察者角色(Watcher)
从AWT1.1开始图形系统的事件模型采用观察者模式,因此观察者模式在Java语言中的地位极其重要。
在xml解析中的SAX也采用了观察者模式来实现。
Java也提供了对观察者模式的内置支持
7.策略模式:
策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式的好处在于你可以动态的改变对象的行为。
策略模式中有三个对象:
(1)环境对象:
该类中实现了对抽象策略中定义的接口或者抽象类的引用。
(2)抽象策略对象:
它可由接口或抽象类来实现。
(3)具体策略对象:
它封装了实现同不功能的不同算法。
Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。
一些Collection允许相同的元素而另一些不行。
一些能排序而另一些不行。
所有实现Collection接口的类都必须提供两个标准的构造函数:
无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。
后一个构造函数允许用户复制一个Collection。
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。
用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。
LinkedList实现了List接口,允许null元素。
此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。
这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
注意LinkedList没有同步方法。
如果多个线程同时访问一个List,则必须自己实现访问同步。
一种解决方法是在创建List时构造一个同步的List:
Listlist=Collections.synchronizedList(newLinkedList(...));
ArrayList实现了可变大小的数组。
它允许所有元素,包括null。
ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。
但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。
其他的方法运行时间为线性。
Vector非常类似ArrayList,但是Vector是同步的。
由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。
Stack继承自Vector,实现一个后进先出的堆栈。
Stack提供5个额外的方法使得Vector得以被当作堆栈使用。
基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。
Stack刚创建后是空栈。
Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
请注意,Map没有继承Collection接口,Map提供key到value的映射。
一个Map中不能包含相同的key,每个key只能映射一个value。
Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
Hashtable继承Map接口,实现一个key-value映射的哈希表。
任何非空(non-null)的对象都可作为key或者value。
添加数据使用put(key,value),取出数据使用get(key),这两个基本操作的时间开销为常数。
Hashtable通过initialcapacity和loadfactor两个参数调整性能。
通常缺省的loadfactor0.75较好地实现了时间和空间的均衡。
增大loadfactor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。
HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即nullvalue和nullkey。
,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。
因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者loadfactor过低。
TreeMap:
该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的Comparator进行排序,具体取决于使用的构造方法。
此实现不是同步的。
Collections工具类:
Arrays:
用于操作数组工具类,里面定义了常见操作数组的静态方法。
常见的有:
二分查找。
排序。
将数组变成字符串。
平衡二叉树:
题目:
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。
要求函数min、push以及pop的时间复杂度都是O
(1)。
因此仅仅只添加一个成员变量存放最小元素(或最小元素的位置)是不够的。
我们需要一个辅助栈。
每次push一个新元素的时候,同时将最小元素(或最小元素的位置。
考虑到栈元素的类型可能是复杂的数据结构,用最小元素的位置将能减少空间消耗)push到辅助栈中;每次pop一个元素出栈的时候,同时pop辅助栈。
题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。
要求时间复杂度为O(n)。
当访问到某一结点时,把该结点添加到路径上,并累加当前结点的值。
如果当前结点为叶结点并且当前路径的和刚好等于输入的整数,则当前的路径符合要求,我们把它打印出来。
如果当前结点不是叶结点,则继续访问它的子结点。
当前结点访问结束后,递归函数将自动回到父结点。
因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好是根结点到父结点的路径。
我们不难看出保存路径的数据结构实际上是一个栈结构,因为路径要与递归调用状态一致,而递归调用本质就是一个压栈和出栈的过程。
题目:
输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点。
用递归和循环两种方法完成树的镜像转换。
用两个栈实现队列:
当m_stack2中不为空时,在m_stack2中的栈顶元素是最先进入队列的元素,可以pop出去。
如果m_stack2为空时,我们把m_stack1中的元素逐个pop出来并push进入m_stack2。
由于先进入队列的元素被压到m_stack1的底端,经过pop和push之后就处于m_stack2的顶端了,又可以直接pop出去。
反转链表:
网易游戏,网易邮箱,有道搜索,网易博客,网易相册,网易泡泡,
网易笔试:
Select*fromUserwhereidAll(selectagefromUser)).
A.selecttop5photoidfromphoto,userwhereuser.userid=photo.useidanduserid=”dragon”orderbyaccesscountdes;
B.Createviewmiddleasselectuserid,sum(size)astotal_sizefromphotogroupbyuseridorderbytotal_size
Selecttop10useridfrommiddle;
C.索引可以加快查询速度。
数据库连接池的作用,设计连接池的时候有哪些注意事项。
.
数据库连接池负责分配、管理和释放数据库连接,数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。
无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。
连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:
1)最小连接数是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费;2)最大连接数是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。
说出数据连接池的工作机制是什么?
J2EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。
客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其标记为“忙”。
如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量由配置参数决定。
当使用的池连接调用完成后,池驱动程序将此连接表记为“空闲”,其他调用就可以使用这个连接。
两阶段提交协议:
可以保证数据的强一致性,许多分布式关系型数据管理系统采用此协议来完成分布式事务。
它是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。
同时也是解决一致性问题的一致性算法。
在两阶段提交协议中,系统一般包含两类机器(或节点):
一类为协调者(coordinator),通常一个系统中只有一个;另一类为事务参与者(participants,cohorts或workers),一般包含多个,在数据存储系统中可以理解为数据副本的个数。
协议中假设每个节点都会记录写前日志(write-aheadlog)并持久性存储,即使节点发生故障日志也不会丢失。
协议中同时假设节点不会发生永久性故障而且任意两个节点都可以互相通信。
当事务的最后一步完成之后,协调器执行协议,参与者根据本地事务能够成功完成提交事务或者回滚事务。
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
例如,银行转帐工作:
从一个帐号扣款并使另一个帐号增款,这两个操作要么都执行,要么都不执行。
数据库事务必须具备ACID特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。
原子性:
指整个数据库事务是不可分割的工作单位。
只有使据库中所有的操作执行成功,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态。
一致性:
指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中Tom和Jack的存款总额为2000元。
隔离性:
指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。
事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
持久性:
指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。
即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
Javaclassload