操作系统
计算机组成原理
一定的汇编语言基础
Java SE有着扎实的基础
并发编程基础【因为虚拟机的设计都需要考虑高并发状态】
Java程序员把控制内存的权力交给了Java虚拟机,一旦出现内存泄露和溢出方面的问题,如果不了解虚拟机的内存管理机制,修正错误将会成为艰难的一项工作。
定义:程序计数器是当前线程所执行的字节码的行号指示器(程序控制流指示器),程序的分支、循环、跳转、异常处理和线程恢复等继承功能都依赖它来实现。特别的是,如果线程正在执行一个Java方法,那么它记录着虚拟机字节码指令的地址;如果执行的是本地(关键字native)方法,那么它记录着空值。
生命周期:它是线程私有的内存,每条线程都有一个独立的程序计数器,各条线程之间互不影响,独立存储;随用户线程的启动和结束而建立和销毁。
OOM:没有任何可能出现OOM的情况。
什么是栈帧?
每个方法被执行时,Java虚拟机都会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等方法有关的信息【参考汇编语言栈的作用】。
什么是局部变量表?
局部变量表存储了方法执行过程中所有的局部变量,包括:基本数据类型、对象引用、方法返回地址(指向一条字节码指令的地址)。
定义:每一个线程中,存储栈帧的栈就是虚拟机栈。每一个方法从被调用到执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
生命周期:它是线程私有的内存,生命周期与线程相同。
OOM:栈深度超出了虚拟机的最大深度,抛出StackOverflow。而假如虚拟机栈支持动态扩展,则虚拟机栈无法申请到足够的内存时,会抛出OutOfMemoryError(OOM)。
和虚拟机栈大致一样,只不过本地方法栈存储的是本地方法(关键字native)的栈帧,而虚拟机栈存储的是Java方法的栈帧。
定义:几乎所有的对象实例以及数组都在堆上分配。(new关键字)
为什么说是几乎所有?
随着即时编译技术及逃逸分析技术的日渐强大,栈上分配、标量替换(应该是两种编译优化技术)已经导致对象实例有可能不在堆中而在栈中了!
什么是经典分代?
新生代和老年代,在GC回收算法中它们会成为主角哦。
在我看来,为什么堆的生命周期没有那么绝对?
大多对象实例是线程共享的(这个很明显吧,这是线程安全问题存在的根本原因),但也有少部分是线程私有的,比如:ThreadLocal<T>它就是线程私有的堆内存区域和TLAB(下面会讲)。
从这,对自己说一句,可以明显看出的是,大多事务都不绝对,一切都是为了更好的运行而设计的,而不是为了规则本身而设计的,别太死板。生命周期由GC回收算法控制。
OOM:堆内存不足以进行对象实例内存分配并且堆再也无法动态拓展时,会抛出OOM。
概括来说,就是这里存储着有关类的一切信息!
永久代、元空间和方法区是什么关系?
永久代、元空间都是方法区的一种实现。在永久代被废除后,方法区的实现就采用元空间。
永久代和元空间有什么不同?
存储位置不同,永久代是堆的一部分,和新生代,老年代地址是连续的,而元空间属于本地内存;
存储内容不同,元空间存储类的元信息,而静态变量和常量池等并入堆中。相当于永久代的数据被分到了堆和元空间中。
但是,同样的,对概念别太死板,虽然现在方法区的实现是元空间,但是,堆中的那部分数据仍然是属于方法区的,也就是堆和方法区(又称非堆)其实并没有那么清晰的界限,都只不过是为了对内存进行更好的分配罢了。
定义:它存储着Class文件信息、运行时常量池、即时编译器编译后的代码缓存等长期存在的数据。

解释什么是常量池?
字符串常量池:存放字符串常量和字符串常量引用(intern存入的字符串常量引用,new方法会创建一个字符串对象同时存入一个字符串常量到池中)的内存区域,里面字符串常量不会重复。原本被归类于方法区,因为长期不会被回收;后被归类于堆,因为方法区太小,容不下这尊大佛了。总结来说就是,字符串常量池逻辑上属于运行时常量池,它原本是运行时常量池的一部分,但由于体积太大,被转移到了堆中。
Class常量池:用于存放编译器生成的Class文件中的各种字面量(Literal)和符号引用(Symbolic References);字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等。符号引用
运行时常量池:运行时常量池可以在运行期间将符号引用解析为直接引用,由运行时常量池存储这些直接引用。也就是说,运行时常量池存储着Class常量池运行期间存入的符号引用,以及由符号引用解析出来的直接引用,还包括运行期间产生的新的常量(关于字符串String中的intern方法,如果字符串常量池中已经存在此字符串常量,不变;而如果不存在,字符串常量池存入此字符串常量的引用)
OOM:当方法区(运行时常量池)无法满足新的内存分配需求时,会抛出OOM。
非JVM管理的一块内存区域。
什么是NIO?
NIO是一种基于通道于缓冲区的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过堆中的DirectByteBuffer对象作为这块内存的应用进行操作,显著提高了Java应用程序的性能。(偷偷占了多的内存能不显著吗?)
产生OOM的原因?
操作系统剩余内存满足不了直接内存的分配需求。

对象内存的分配方式有哪些?
指针碰撞:把指针向空闲空间方向挪动一段与对象大小相等的距离。
空闲列表:虚拟机维护一个列表,记录哪块内存是可用的,从列表中利用分配算法找到一块足够大的空间划分给对象实例,并更新列表,会产生外部碎片。
具体选择哪种方式取决于虚拟机的垃圾回收策略,这种两种内存方式参考了操作系统的内存分配策略。
内存分配的并发问题如何解决?
同步处理:利用CAS算法(Compare And Swap)配上失败重试机制,保证分配内存操作的原子性。
TLAB:Thread Local Allocation Buffer,每个线程先在线程的本地缓冲区中分配,本地缓存区用完了再利用同步处理分配线程的本地缓存区。
可以使用-XX:+/-UseTLAB来配置TLAB。
对象头、实例数据和对齐填充。
对象头存储着什么信息?
一部分是用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁(客户端锁定)、偏向线程ID、偏向时间戳等。
另一部分用于存储类型指针,即对象指向它的类型元数据的指针,通过这个来确定对象是哪个类的实例。(反射会用到)如果是数组,还会存储数组的长度,因为一般的对象实例通过元数据信息已经可以确定大小,而数组不行。
实例数据存储着什么信息?
程序代码里所定义的各种类型的字段内容。
为什么要对齐填充?
就和计网IP数据报以及计组里学的一样,数据最好封装成字节的整数倍,方便CPU读取。
如果使用句柄访问,在java堆中将划分出一块内存来作为句柄池。reference中存储的就是对象的句柄地址,而句柄中包含对象实例数据与类型数据具体地址信息。

使用直接访问,在java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息。reference中直接存储对象地址即可。

句柄访问在引用和具体数据之间增加了一层转换关系,这层转换关系使得对象在被移动的时候(如垃圾回收)只需要改变转换关系,即改变句柄池中的引用指向即可。而引用本身不需要被修改。使用直接访问最大的好处就是快,因为相对于句柄访问减少了一次指针定位的时间。由于java是面向对象语言,对象访问非常频繁,因此这种访问开销积少成多也非常可可观。hotspot虚拟机使用的就是直接访问方式。
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/