JVM如何分配此内存

时间:2014-12-07 21:53:49

标签: java arrays string

如果你在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);

5 个答案:

答案 0 :(得分:3)

嗯,你真的在​​这里问了两个问题。

首先,declaring数组(任何深度)都不会在Java中分配内存,而在C示例中,您声明定义数组,其中< em> 分配内存。

爪哇:

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;

...只是对 String对象引用数组的引用 。没什么。

即使您创建阵列......

foo = new String[20];

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

当您实际向该阵列添加字符串时......

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

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

同样,请记住strings are immutable,因此JVM不必担心realloc他们。


关于字符串的问题对于Java来说很棘手,因为Java只需要另外一个类(String)并将其转换为语言结构(如最后一个代码示例所示)。难怪在考虑内存和分配时,字符串可能会令人困惑。

答案 1 :(得分:2)

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

  

String类表示字符串。 Java程序中的所有字符串文字,例如&#34; abc&#34;,都是作为此类的实例实现的。

     

字符串是不变的;它们的值在创建后无法更改。字符串缓冲区支持可变字符串。因为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个对象的数组(数组和字符串)。最终,当它们不再被引用时,这些都将被垃圾收集。

答案 2 :(得分:1)

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

到此声明完成时,您可以参考N + 1个新对象:

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

答案 3 :(得分:0)

我也有一些C背景。在Java中,某些东西的数组与C中的完全相同。它是一个指针数组(或者只是像int这样的基类型)。数组的大小必须可用于Java,以及

String[] words = new String[10];

您的示例将单词声明为字符串数组,从而产生变量&#39;单词&#39;使用指向字符串数组的空指针。我的例子将指出&#39;单词&#39;到10个指向字符串的数组。

查看API java.util.arrays

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

答案 4 :(得分:0)

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