在互联网上有各种各样的文章,试图通过经验估计java.lang.Object
特定JVM实现的开销.例如,我在一些JVM中看到了一个Object
估计为8字节的裸大小开销.
我想知道的是,extends
关系的典型JVM实现是否在类层次结构的每个级别引入增量大小开销.换句话说,假设您有一个具有N级子类的类层次结构.是类实例O(1)还是O(N)的内存中表示的开销?
我想它是O(1)因为虽然你需要成为Java Object
(vtable,类链)的一些隐藏的蓬松东西的大小会随着继承层次结构的增长而增长,但它们每个类增长,而不是每个实例,JVM实现可以在连接到每个实体的常量大小的头中存储这些实体的常量大小的指针Object
.
所以从理论上讲,直接附加到任何Java对象的内存中表示的开销应该是O(1)的继承深度N.有谁知道它在实践中是否正确?
众所周知,通过使用类型参数,您可以在Java中使用泛型类:
class Foo<T> {
T tee;
Foo(T tee) {
this.tee = tee;
}
}
Run Code Online (Sandbox Code Playgroud)
但是您也可以使用泛型构造函数,这意味着构造函数显式接收它们自己的泛型类型参数,例如:
class Bar {
<U> Bar(U you) {
// Why!?
}
}
Run Code Online (Sandbox Code Playgroud)
我很难理解用例.这个功能让我做了什么?
我有一个号码的C++函数void f()
,R g(T a)
,S h(U a, V b)
等.我想写一个接受一个模板功能f
,g
,h
等作为模板参数,并调用该函数.
即我想要这样的东西:
template<MagicStuff, WrappedFunction>
ReturnType wrapper(MagicallyCorrectParams... params)
{
extra_processing(); // Extra stuff that the wrapper adds
return WrappedFunction(params);
}
...
wrapper<f>(); // calls f
wrapper<g>(T()); // calls g
wrapper<h>(U(), V()); // calls h
Run Code Online (Sandbox Code Playgroud)
template<typename ReturnType, typename Args...>
ReturnType wrapper(ReturnType (*wrappee)(Args...), Args... args)
{
extra_processing();
return wrappee(args...);
}
...
wrapper(f); // calls f OK
wrapper(g, T()); …
Run Code Online (Sandbox Code Playgroud) 我有一个简单的问题:我想"yyyyMMdd"
严格地解析格式化的Java字符串,因此这"19800229"
是一个有效的日期,但事实"19820229"
并非如此.假设这些是正常公历的AD日期.
我正在尝试使用java.time
JDK 8中的新软件包来解决这个问题,但事实证明它比希望的更复杂.我目前的代码是:
private static final DateTimeFormatter FORMAT = DateTimeFormatter
.ofPattern("yyyyMMdd").withChronology(IsoChronology.INSTANCE)
.withResolverStyle(STRICT);
public static LocalDate parse(String yyyyMMdd) {
return LocalDate.parse(yyyyMMdd, FORMAT);
}
Run Code Online (Sandbox Code Playgroud)
但是,解析诸如"19800228"之类的有效日期对我来说产生了一个难以理解的错误:
java.time.format.DateTimeParseException:无法解析文本'19820228':无法从TemporalAccessor获取LocalDate:{MonthOfYear = 2,DayOfMonth = 28,YearOfEra = 1982},ISO类型为java.time.format.Parsed
我如何使用java.time.format.DateTimeFormatter
来解决我的简单用例?
是检查WS_CHILD位:
LONG style = GetWindowLong(hwnd, GWL_STYLE);
int isTopLevel = !(style & WS_CHILD);
Run Code Online (Sandbox Code Playgroud)
或者,还有更好的方法?
假设:Straight C只调用现有的Windows API代码.
我一直在阅读Windows x64 ABI上很长篇的非常好的文章目录.这些文章的一个非常小的方面是帧指针的描述.一般要点是,因为Windows x64调用堆栈规则非常严格,所以通常不需要专用的帧指针,尽管它是可选的.
我一直注意到的一个例外是当alloca()
用于在堆栈上动态分配内存时.这样做的功能显然需要一个帧指针.例如,引用微软关于"堆栈分配"的文档(斜体和粗体由我添加):
如果在函数中动态分配空间(alloca),则必须使用非易失性寄存器作为帧指针来标记堆栈固定部分的基础,并且必须在prolog中保存和初始化该寄存器.请注意,当使用alloca时,来自同一调用者的对同一被调用者的调用可能具有其寄存器参数的不同家庭地址.
对此,Microsoft的x64 ABI alloca()
文档密码添加:
_alloca需要16字节对齐,并且还需要使用帧指针.
首先,为什么必须使用它?我假设在异常时调用堆栈展开,但我还没有找到令人满意的解释.
下一个问题:它必须指向哪里?在上述两个引文中的第一个中,它表示"必须"用于标记" 堆栈的固定部分 "的基础.什么是"堆栈的固定部分"?我得到的印象是,这个术语在给定的框架中表示包含的地址范围(较高地址到较低地址):
同样,我还没有找到这个"固定部分"的令人满意的定义.我上面链接的"堆栈分配"页面包含下面的图表以及"如果使用,则堆栈指针通常指向此处":
这个非常漂亮的博客文章同样含糊不清,包括一个图表,说明框架指针"点在这里的某处",其中"here"是保存的非易失性寄存器和本地的地址.
最后一点含糊不清,来自微软的MSDN文章"动态参数堆栈区域构建",其中仅包含以下内容:
如果使用帧指针,则存在动态创建参数堆栈区域的选项.目前在x64编译器中没有这样做.
"一般"是什么意思?"在这里的某个地方"在哪里?存在的选项是什么?有规则吗?谁在乎?
或者,tl;博士:标题要求什么.任何包含带注释的程序集的答案都会感激不尽.
我有一个琐碎的单身课程.我的singleton.h
文件看起来像这样:
class singleton
{
...
public:
static singleton& instance();
};
Run Code Online (Sandbox Code Playgroud)
我singleton.cpp
看起来像这样:
...
singleton& singleton::instance()
{
static singleton * const _instance(new singleton);
return *_instance;
}
Run Code Online (Sandbox Code Playgroud)
在编写这个类时,我认为我依赖于线程安全的函数本地静态初始化,我理解这将在这里描述的C++标准的第6.7节中阐述.希望我明白这是如何工作的.
我正在使用2013年11月的CTP工具链运行Visual C++ .微软称2013年11月CTP支持线程安全的函数本地静态初始化,并快速浏览编译器生成的目标代码,表明它正在尝试这样做.
我的问题是,在另一个翻译单元中销毁静态存储持续时间对象需要访问singleton::instance()
.我预计这不会有任何困难,因为静态变量支持singleton::instance()
是一个永不删除的指针.但是,singleton::instance()
来自该其他对象的调用正在崩溃我的进程,堆栈跟踪如下所示:
_Init_thread_header
singleton::instance
other_translation_unit_object::~other_translation_unit_object
Run Code Online (Sandbox Code Playgroud)
其中_Init_thread_header()
似乎是由编译器插入来实现线程安全的静态初始化.
所以我的问题是:上面的代码是否表明我从根本上误解了静态初始化应该如何工作(最可能的情况是,如果是这样,那就好了:),或者是否有可能出现其他问题?
将BigDecimal
包含任意值的Java简化为规范形式的最简单方法是什么,以便BigDecimal
使用该equals()
方法将两个代表相同数字的数字相等?
我使用这样的代码从任意字符串解析我的数字:
BigDecimal x = new BigDecimal(string1, MathContext.DECIMAL64);
BigDecimal y = new BigDecimal(string2, MathContext.DECIMAL64);
Run Code Online (Sandbox Code Playgroud)
由于(string1
,string2
)是任意的,它们可以是,例如,("1"
,"1.0000"
)或("-32.5"
,"1981"
)......
我正在寻找的是该方法的最简单(最短/最干净的代码)实现规范化,以上断言
assert x.compareTo(y) != 0 ||
(canonicalize(x).equals(canonicalize(y)) &&
x.compareTo(canonicalize(x)) == 0 && y.compareTo(canonicalize(y)) == 0);
Run Code Online (Sandbox Code Playgroud)
将会成功...:
public static BigDecimal canonicalize(BigDecimal b) {
// TODO:
}
Run Code Online (Sandbox Code Playgroud) 我有一个名为接口Bar
和通用类Foo
参数上的类型是 Bar
:
class Foo<B extends Bar> { }
Run Code Online (Sandbox Code Playgroud)
我的类有一个通用构造函数,它带有a Class
和a Stream
:
class Foo<B extends Bar> {
B[] bs;
Foo(Class<B> clazz, Stream<B> stream) { // General ctor
bs = someFunctionOf(clazz, stream);
}
}
Run Code Online (Sandbox Code Playgroud)
我想添加一个专门的构造函数,是要求其实际方法参数两者是Bar
和一enum
类,这样我可以从特殊的构造函数中调用我的通用构造函数:
class Foo<B extends Bar> {
B[] bs;
Foo(Class<B> clazz, Stream<B> stream) { // General ctor
bs = someFunctionOf(clazz, stream);
}
// FIX THIS ----+
// |
// ?
Foo(Class<Something> clazz) { // …
Run Code Online (Sandbox Code Playgroud) 我有一个使用Kotlin Gradle插件的Gradle项目.我想构建一个Java 9模块,所以我的目录结构如下所示:
src/main/java/
- module-info.java
src/main/kotlin/
- Foo.kt
- Bar.kt
build.gradle
...
Run Code Online (Sandbox Code Playgroud)
我build.gradle
声明了以下依赖项:
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.10"
compile "org.jetbrains.kotlin:kotlin-reflect:1.2.10"
compile "org.junit.jupiter:junit-jupiter-api:5.0.2"
}
Run Code Online (Sandbox Code Playgroud)
我用所有这些依赖于我的科特林源(Foo.kt
,Bar.kt
,...).
如果我module-info.java
这么写,那么一切都很有效:
module my.module {
requires kotlin.stdlib;
exports my.module.pkg;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用这种技术javac
在compileJava
任务期间提供所有编译时依赖项.
但是,如果我-Xlint:all
在compileJava
任务期间(编译module-info.java
)打开Java编译器,我会收到以下警告:
/path/to/my.module/src/main/java/module-info.java:26: warning: requires directive for an automatic module
requires kotlin.stdlib;
^
Run Code Online (Sandbox Code Playgroud)
所以这里我们有Java编译器,javac
抱怨这kotlin.stdlib
是一个自动模块,所以我不应该有requires
它的子句.
但是,如果我删除该requires
条款以使其变得javac
快乐,那么它就会kotlinc
变得更加愤怒 …
java ×6
c++ ×3
c ×2
c++11 ×2
constructor ×2
generics ×2
windows ×2
64-bit ×1
assembly ×1
bigdecimal ×1
bounds ×1
date ×1
datetime ×1
equals ×1
gradle ×1
inheritance ×1
java-8 ×1
java-module ×1
java-platform-module-system ×1
jvm ×1
kotlin ×1
math ×1
oop ×1
parsing ×1
singleton ×1
templates ×1
visual-c++ ×1
winapi ×1