当你new Object()在Java中执行时,jvm是使用无锁算法来分配内存还是需要锁定?
在这种情况下我指的JVM是Hotspot VM.从我所知道的一点点来看,它只需要增加一个指针以超快地分配内存.但是在多线程的情况下,这种增量是否需要锁定或CAS?
观看通用VM演示文稿,我研究了这张幻灯片,其中列出了HotSpot JIT所做的所有优化:
在该language-specific techniques部分中有一个去反射.我试图在互联网上找到有关它的一些信息,但失败了.我知道这种优化在某种程度上消除了反射成本,但我对细节很感兴趣.有人可以澄清一下,还是给出一些有用的链接?
在对应用程序进行一些更改之后,它遭受了显着的性能下降,并且在调查中,最常调用的方法之一不再被编译.启用:-XX:+LogCompilation显示在更改之前,此方法是:排队进行编译,编译,然后成功内联到调用者; 而在更改之后,没有编译尝试的记录,并且内联尝试说:
inline_fail reason ='not compilable(disabled)'
原始方法如下,其中_maxRepeats一个实例变量声明为a Map(没有泛型,很久以前编写的代码),使用的是键是类的对象,DadNode值是a Integer.
private int cnsGetMaxRepeats(DadNode dn) {
if (_maxRepeats != null) {
Integer max = (Integer)_maxRepeats.get(dn);
if (max != null) {
return max;
}
}
return dn.getMaxOccurs().getValue();
}
Run Code Online (Sandbox Code Playgroud)
修正案涉及将_maxRepeats地图更改为使用泛型:
Map<Integer, Integer>
Run Code Online (Sandbox Code Playgroud)
并在方法中添加了一个新参数:
private int cnsGetMaxRepeats(int childIdx, DadNode dn) {
if (_maxRepeats != null) {
Integer max = _maxRepeats.get(childIdx);
if (max != null) {
return max;
}
}
return dn.getMaxOccurs().getValue();
}
Run Code Online (Sandbox Code Playgroud)
使用显式调用Integer.valueOf和 …
根据此链接,可以选择手动设置MaxRamSize以限制JVM不使用超出此范围的内存.但我没有看到任何相同的文件.我从来不知道这一点.有这样的东西还是类似的东西?PS.我知道,我不打算设置堆/堆栈/元空间/本机内存大小.我只是想知道是否有整体内存限制选项.
尝试它没有帮助,因为它错误:
Improperly specified VM option 'MaxRAM=1073741824B'
Could not create the Java Virtual Machine.
A fatal exception has occurred. Program will exit.
Run Code Online (Sandbox Code Playgroud)
事实上根据这个链接 open-jdk似乎有这些选项.我发现的另一个链接指向设置堆大小.这也是不寻找的.但我认为这是针对Oracle的.
为什么我正在寻找这种选项来在容器(如Docker)中运行应用程序,并防止应用程序被OOM Killer杀死.我相信如果有一个这样的java应用程序的设置会错误或崩溃,java.lang.OutOfMemoryError而不是容器被终止.
我的假设和理解可能完全错误.这个问题也可能是完全错误和无关紧要的.但当然,要求是前进的方向:).
通过阅读相当成熟的Oracle博客文章,我了解到了这一点
(......)目前正在连续收集永久性一代.
然而,这篇博客文章来自几年前,我想知道垃圾收集算法的最新进展如何可能改变了这种说法的准确性.我特别想知道甲骨文所描述的新的G1垃圾收集器:
旧的垃圾收集器(串行,并行,CMS)都将堆构建为三个部分:年轻代,旧代和永久生成固定内存大小.(...)执行垃圾收集时,G1以类似于CMS收集器的方式运行.
但是再也没有在整个教程中提到永久代.
从阅读有关CMS - 根据上述声明的工作方式类似于G1 - 我没有找到关于永久世代的任何明确信息,但从其他博客条目中了解到
(...)Concurrent Mark和Sweep根本不紧凑.一旦无法再分配对象,就会触发串行主GC.
因此,我想知道现代垃圾收集器,例如CMS或G1,是否完全忽略了永久性生成并将其留给完整的GC调用,这些调用运行旧的串行GC以清除永久代(同时此序列GC也收集年轻和连续成熟的世代,当使用G1代替CMS时,我不理解这是不可取的.我主要想知道在STW和收集时间方面对永久代进行垃圾收集是否比收集终生代更加昂贵.
奖金问题:Oracle教程提到永久生成是堆的一部分.我一直认为永久生成是在堆外明确分配的.最近的HotSpot实现中是否有此更改?
谢谢您的帮助!
到目前为止,我知道:
我的问题是:
没有找到任何关于此的文档.
注意:此问题与volatile,AtomicLong或所描述的用例中的任何感知缺陷无关.
鉴于以下内容:
- 最近的64位OpenJDK 7/8(最好7位,但8位也很有帮助)
- 多处理英特尔基础系统
- 非易失性长原始变量
- 多个不同步的mutator线程
- 一个不同步的观察者线程
观察者是否始终保证会遇到由变异线程写的完整值,或者是撕裂危险的单词?
此属性对于32位基元和64位对象引用是存在的,但是对于long和double,JLS不保证:
17.7.非原子对double和long的处理:
出于Java编程语言内存模型的目的,对非易失性long或double值的单次写入被视为两个单独的写入:每个32位一半写入一次.这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二次32位的情况.
但是抱着你的马:
[...]为了效率,这种行为是特定于实现的; Java虚拟机的实现可以自由地以原子方式或分两部分执行对long和double值的写入.鼓励Java虚拟机的实现避免在可能的情况下拆分64位值.[...]
因此,JLS 允许 JVM实现拆分64位写入,并鼓励开发人员相应地进行调整,但也鼓励 JVM实现者坚持使用64位写入.我们还没有回答最新版本的HotSpot.
由于单词撕裂最有可能发生在紧密循环和其他热点的范围内,我试图分析JIT编译的实际汇编输出.长话短说:需要进一步测试,但我只能在long上看到原子64位操作.
我使用了hdis,一个OpenJDK的反汇编插件.在我老化的OpenJDK 7u25版本中构建并安装了插件之后,我开始编写一个简短的程序:
public class Counter {
static long counter = 0;
public static void main(String[] _) {
for (long i = (long)1e12; i < (long)1e12 + 1e5; i++)
put(i);
System.out.println(counter);
}
static void put(long v) {
counter += v;
}
}
Run Code Online (Sandbox Code Playgroud)
我确保始终使用大于MAX_INT(1e12到1e12 + 1e5)的值,并重复操作足够的次数(1e5)以触发JIT.
编译后,我用hdis执行Counter.main(),如下所示:
java -XX:+UnlockDiagnosticVMOptions \
-XX:PrintAssemblyOptions=intel \
-XX:CompileCommand=print,Counter.put …Run Code Online (Sandbox Code Playgroud) 当我尝试在项目中使用已更改的方法主体重新加载类(热交换)时出现此错误.在一切正常之前,但突然停止,我不记得什么可能是一个原因.有什么奇怪我有另一个项目具有相同的设置和方法体的热交换工作正常.
以下是NOT-working项目的配置:


我的VM设置:
-XX:PermSize=512m
-XX:MaxPermSize=1024m
-Xms1024m
-Xmx2048m
-Dcatalina.home="C:\Programy\apache-tomcat-7.0.57"
-Djava.endorsed.dirs="C:\Programy\apache-tomcat-7.0.57\endorsed"
-javaagent:C:\Programy\apache-tomcat-7.0.57/lib/spring-instrument-3.1.2.RELEASE.jar
-Dspring.profiles.active=closeMonthTest
-Dnpk.jobs.enabled=true
Run Code Online (Sandbox Code Playgroud)
这是我工作项目的配置:


VM选项:
-XX:PermSize=512m
-XX:MaxPermSize=1024m
-Xms1024m
-Xmx2048m
-Dcatalina.home="C:\Programy\apache-tomcat-7.0.57"
-Djava.endorsed.dirs="C:\Programy\apache-tomcat-7.0.57\endorsed"
-javaagent:C:\Programy\apache-tomcat-7.0.57/lib/spring-instrument-3.1.2.RELEASE.jar
-Dspring.profiles.active=test
Run Code Online (Sandbox Code Playgroud) 我正在运行时为各种目的检测类文件.我正在使用JVMTI代理.我测试方法的策略是调用RetransformClasses函数来调用ClassFileLoadHook.此策略适用于在检测时间之后进一步调用的所有方法,因为实际检测在后续函数调用中发生,但它不适用于任何没有进一步调用的方法,如main程序中的函数.
我想在执行过程中即时检测方法.我想要一些程序,如检测代码的堆栈替换(OSR).在JVMTI或任何其他方法中是否有任何策略?
PS:如果能有所帮助,我愿意编辑/修补OpenJDK源代码.
我有以下课程.
我已经使用javac手动编译了类并运行了Driver该类.
后来删除了entity.class和MyCustomException.class运行应用程序,如下所示.
java驱动程序测试
以下错误被抱怨MyCustomException丢失但不是关于Entity班级.所以,不清楚为什么JRE抱怨MyCustomException课而不是Entity课.
确实我已经删除了代码,throw new MyCustomException();但我没有遇到关于Entity类的错误.
Caused by: java.lang.NoClassDefFoundError: com/techdisqus/exception/MyCustomException
Run Code Online (Sandbox Code Playgroud)
请注意,IF条件不会被执行,因为我将命令参数作为测试传递
为什么抛出异常会导致加载MyCustomException永远不会执行的异常,但除非条件满足,否则JVM不会加载任何其他常规类,如此处的Entity类所示.请检查Driver.java下面.
MyCustomException.java
public class MyCustomException extends RuntimeException {
}
Run Code Online (Sandbox Code Playgroud)
Entity.java
public class Entity {
}
Run Code Online (Sandbox Code Playgroud)
Driver.java
public class Driver {
public static void main(String[] args) {
String s = args[0];
if("true".equals(s)){ …Run Code Online (Sandbox Code Playgroud) jvm-hotspot ×10
java ×9
jvm ×6
jit ×2
bytecode ×1
concurrency ×1
heap-memory ×1
hotswap ×1
java-8 ×1
jvmti ×1
memory ×1
optimization ×1
performance ×1
tomcat ×1