前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
运行时数据区分为线程共享区和线程私有区。 线程共享区是所有线程共享的内存区域包括方法区和堆区。 线程私有区是每个线程独有的一份内存区域,分为虚拟机栈、本地方法栈、程序计数器。


public class JVMStack {
public static void main(String[] args) {
methodA();
}
public static void methodA(){
methodB();
}
public static void methodB(){
methodC();
}
public static void methodC(){
System.out.println("methodC()");
}
}
因为虚拟机栈后进先出,所以出栈顺序是相反的,methodC运行完出栈,接着就是methodB、methodA,直至main方法运行结束。
2. 栈帧执行流程先看一段简单的代码:public class FrameStacks {
public static void main(String[] args) {
FrameStacks frameStacks = new FrameStacks();
frameStacks.add();
}
public int add(){
int a = 2;
int b = 3;
int c = (a + b)*4;
return c;
}
}
因为add是个实例方法,所以局部变量表中第0位索引的变量槽默认是用于传递方法所属对象实例的引用,在方法中可以通过关键字“this”来访问到这个隐含的参数。也可以通过javap -v FrameStacks.class 来看下局部变量表结构,可以看到第0位索引存放的是this。
再通过javap -c FrameStacks.class命令看下add方法的字节码:public int add();
Code:
0: iconst_2
1: istore_1
2: iconst_3
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: iconst_4
8: imul
9: istore_3
10: iload_3
11: ireturn0: iconst_2 -> 将a=2加载到操作数栈
1: istore_1 -> 把a从操作数栈出栈并储存到局部变量表下标为1的位置
2: iconst_3 -> 将b=3加载到操作数栈
3: istore_2 -> 把b从操作数栈出栈并储存到局部变量表下标为2的位置
4: iload_1 -> 把a从局部变量表加载到操作数栈
5: iload_2 -> 把b从局部变量表加载到操作数栈
6: iadd -> 把操作数栈栈顶的两个值a和b相加,相加的动作是在执行引擎做的,加完之后自动入操作数栈
7: iconst_4 -> 把常量4加载到操作数栈栈顶
8: imul -> 把a和b的和乘以4,同样在执行引擎计算,计算之后自动入栈顶
9: istore_3 -> 把imul得到的结果c从操作数栈出栈并存储到局部变量表下标为3的位置
10: iload_3 -> 把c从局部变量表加载到操作数栈
11: ireturn -> 把操作数栈中的结果c返回
在jdk1.8.0_152\jre\bin目录下找到sawindbg.dll文件,复制一份到jre\bin目录下。 进入jdk1.8.0_152\lib目录,通过命令行执行java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB ,执行完时候会出现如下窗口
3.2 修改上面例子的代码public class FrameStacks {
public static void main(String[] args) throws InterruptedException {
FrameStacks frameStacks = new FrameStacks();
frameStacks.add(4);
}
public int add(int c) throws InterruptedException {
int a = 2;
int b = 3;
int d = (a + b)*c;
Thread.sleep(Integer.MAX_VALUE);
return d;
}
}
打开JHSDB窗口
打开之后可以看到有好几个线程启动,我们只要选择main线程就行,然后选择左上角Stack Memory查看栈内存
一个栈帧的开始是从Interpreted frame部分开始的。 第一个栈帧是当前正在执行的栈帧,在这里是Thread.sleep方法的栈帧,sleep方法是native方法,因此当前是本地方法栈,也从侧面证明了Hotspot虚拟机的本地方法栈和虚拟机栈是合二为一的。 第二个是方法add方法的栈帧、第三个是main方法的栈帧,可以看到add方法栈帧的局部变量表(locals area)部分和main方法栈帧的操作数栈(expression stack)有重合,也就是蓝色方框部分,这段区域就是共享部分,也是Hotspot虚拟机对栈帧的优化。
package jvm;
public class HeapObject{
public static void main(String[] args) throws InterruptedException {
Student studentSun = new Student();
studentSun.setUsername("sun");
studentSun.setAge(18);
System.gc();
Student studentArron = new Student();
studentArron.setUsername("Arron");
studentArron.setAge(17);
Thread.sleep(Integer.MAX_VALUE);
}
}
class Student{
private String username;
private Integer age;
// 省略get/set方法
}
-XX:+UseConcMarkSweepGC的作用是使用CMS垃圾收集器。这样能更好的查看堆的分代情况,关于CMS垃圾收集器可自行了解,这里不做过多解释。 -XX:-UseCompressedOops 禁止指针压缩,JHSDB对指针压缩存在缺陷,建议关闭指针压缩 -Xmx10m 设置堆的最大内存为10M,在这里是为了JHSDB加快在内存中搜索对象的速度然后在通过jps命令查看HeapObject进程ID
进程id获取到之后通过JHSDB查看具体信息,在Tools -> Object Histogram中查看类的描述信息,通过类的全限定名搜索Student类。
找到之后双击查看类的描述,这里new 了两个Student对象,会看到两个对象信息。
然后通过下方的Inspect 按钮分别查看两个对象地址对应的哪个对象
从Inspector中我们可以看到 studentSun对象的内存地址是0x0000000013832558 studentArron对象的内存地址是0x0000000013400000再在Tools -> Heap Parameters中查看堆内存分代情况
eden区的起始地址:[0x0000000013400000 ~ 0x00000000136b0000)
from 起始地址:[0x00000000136b0000 ~ 0x0000000013700000)
to 起始地址: [0x0000000013700000 ~ 0x0000000013750000)
Tenured 起始地址: [ 0x0000000013750000 ~ 0x0000000013e00000)能力一般,水平有限,如有错误,请多指出。 如果对你有用点个关注给个赞呗 更多文章可以关注一下我的微信公众号suncodernote
参考书籍 《深入了解JVM虚拟机》
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://