繁体   English   中英

JVM如何分配此内存

[英]How does JVM allocate this memory

如果您在Java中像这样声明字符串数组

String[] words;

那只是给您一个正确的参考?

现在,我来自C语言的背景,所以我知道C语言中的“字符串”数组是指向指针的指针,或者是数组的数组。 但是,我想知道JVM如何使用此声明...它只是一个引用吗? 然后,当您给它足够的内存时,它也会为字符串提供不同的长度吗?

我很难形容,但我知道字符串只是字符数组,因此JVM如何在分配字符串之前确定字符串有多长时间? 它是否以新的更新字符串长度重新分配整个字符串数组。

char array[6][6]; //in C this is necessary because it needs to know the column and row length

与此类似

char* array[5]; // you still need to malloc the slots in the array for a two dimensional length to be achieved

但是在Java中我不知道它如何工作

  String line = null;
    try {
        while ((line = bfr.readLine()) != null) {
            if (StringUtils.isBlank(line))
                continue;

            System.out.println(line);
            String[] chunks = line.split(","); //this line right here, how does JVM allocate proper memory
            MindsparkPartnerCode record = new MindsparkPartnerCode();

            record.setIEFFCode(chunks[0]);
            records.add(record);

好吧,您实际上是在问两个问题。

首先,在Java中声明一个数组(任何深度)都不会分配内存,而在您的C示例中,您声明定义了一个数组,它分配内存。

Java:

String[] words; // Just a reference (null at this point) -- no memory allocated

C:

char array[6][10]; // *Does* allocate 60 bytes of memory, usually on the stack.

在Java中,在使用new运算符之前,不会分配任何内存(当然,对于基元除外)。

Foo bar; // Just a reference
bar = new Foo(); // NOW memory has been allocated.

new返回对新对象的引用 将不是原始元素的所有内容都视为参考(包括数组!)。


字符串没有什么不同。

String[] foo;

...只是为字符串对象引用的数组引用 而已。

即使您创建数组...

foo = new String[20];

... Java分配20 * sizeof(JavaReference)字节(其中JavaReference是JVM用于表示引用的任何基础类型)。 因此,现在知道数组的大小。

当您实际将字符串添加到该数组时...

foo[0] = "Hello!"; // Which is essentially...
foo[0] = new String("Hello!");

...... 就是当你告诉你的JVM字符串有多长,从而告诉它分配(strlen("Hello!") + 1) * 2个字节(因为Java的存储其字符串以UTF-16编码)。

还有,请记住, 字符串是不可变的,所以JVM不必担心realloc “荷兰国际集团他们。


关于Java,关于字符串的问题很棘手,因为Java接受了另外一个类( String ),然后将其转换为语言结构(如最后一个代码示例所示)。 难怪在考虑内存和分配时字符串会造成混乱。

在Java中, String不是字符数组。 它是对堆上类java.lang.String垃圾回收实例的引用。 从文档:

String类表示字符串。 Java程序中的所有字符串文字(例如“ abc”)都实现为此类的实例。

字符串是常量; 它们的值创建后无法更改。 字符串缓冲区支持可变字符串。 由于String对象是不可变的,因此可以共享它们。 例如:

  String str = "abc"; 

等效于:

  char data[] = {'a', 'b', 'c'}; String str = new String(data); 

String类包含一些方法,这些方法可以检查序列中的各个字符,比较字符串,搜索字符串,提取子字符串以及创建字符串的副本,并将所有字符都转换为大写或小写。 大小写映射基于Character类指定的Unicode标准版本。

Java语言为字符串连接运算符(+)以及将其他对象转换为字符串提供了特殊的支持。 字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。 字符串转换是通过toString方法实现的,该方法由Object定义并由Java中的所有类继承...

因此可以从一个字符数组创建一个String ,但它不仅仅是一个字符数组。 该类内置于Java本身,因此编译器知道如何从键入代码的字符串文字中实例化该类的实例。

因此,当您执行以下操作时:

String[] chunks = line.split(",");

您在类java.lang.String的实例上调用split方法。 它返回给您一个java.lang.String对象数组, 对象将自己分配 (数组和字符串)。 最终,当它们不再被引用时,将全部被垃圾回收。

 String[] chunks = line.split(","); //this line right here, how does JVM allocate proper memory

在此语句完成时,将可以引用N + 1个新对象:

  • 一个String[]数组对象
  • N个String对象,每个对象位于数组的每个插槽中

我也有一些C背景。 在Java中,某些事物的数组与C中的完全相同。它是一个指针数组(或仅是基本类型(如ints))。 数组的大小必须对Java一样可用,例如

String[] words = new String[10];

您的示例将单词声明为字符串数组,从而导致变量“ words”具有指向字符串数组的空指针。 我的示例将“单词”指向由10个指向字符串的指针组成的数组。

看看API java.util.arrays

https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html

它为其他堆对象分配一个引用数组。 Java中的大写S字符串本身就是对堆上对象的引用,而该对象又包含对char []的引用,该char []可以具有任意大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM