21

I was playing with Java Reflection API and observed that methods with variadic argument list become transient. Why is that and what does transient keyword mean in this context?

From Java Glossary, transient:

A keyword in the Java programming language that indicates that a field is not part of the serialized form of an object. When an object is serialized, the values of its transient fields are not included in the serial representation, while the values of its non-transient fields are included.

However this definition does not say anything about methods. Any ideas?

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Dummy {
    public static void main(String[] args) {
        for(Method m : Dummy.class.getDeclaredMethods()){
            System.out.println(m.getName() + " --> "+Modifier.toString(m.getModifiers()));
        }
    }

    public static void foo(int... args){}
}

Outputs:

main --> public static
foo --> public static transient
ahmet alp balkan
  • 42,679
  • 38
  • 138
  • 214

3 Answers3

21

Sort of an answer can be found in the code of javassist AccessFlag

public static final int TRANSIENT = 0x0080;
public static final int VARARGS   = 0x0080;

It appears both have the same values. And since transient means nothing for methods, while varargs means nothing for fields, it is ok for them to be the same.

But it is not OK for the Modifier class not to take this into account. I'd file an issue about it. It needs a new constant - VARARGS and a new method - isVarargs(..). And the toString() method can be rewritten to include "transient/varargs".

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 2
    the Modifier.toString() takes a single int and.. takes it from there; since there is no difference field/method, it can never be correct – bestsss Feb 08 '11 at 18:48
  • @bestsss - that's true. But another method can be added that takes `AccessibleObject` as argument as well. Or just to add both the the message (see my update) – Bozho Feb 08 '11 at 18:49
  • `AccessibleObject` won't work for Class, needs to be just Object – bestsss Feb 08 '11 at 18:53
  • Reflection Modifier API is underengineered. As so many parts of Java I thing we will have to live with that. Its 2016 and I am still running in the same problem with Java 8. – Martin Kersten Aug 20 '16 at 10:50
  • @Martin Kersten: The documentation of [`Modifier.toString(int)`](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Modifier.html#toString-int-), says that you should first AND the bits with [`methodModifiers()`](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Modifier.html#methodModifiers--) to get the correct result for a method (official solution since Java 7). Though, of course, it’s easier to just use `Method.toString()`, which is the only way to get Java 8’s `default` modifier where appropriate… – Holger Sep 27 '16 at 16:21
  • 'But it is not OK for the `Modifier` class not to take this into account': It is not *possible* for the `Modifier` class to take this into account. It doesn't know where the flags came from. – user207421 Mar 21 '21 at 02:46
6

This looks like a bug in the implementation. I think that the root cause might be that the bit set in the .class file for transient fields is the same for varargs methods (see http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf, pages 122 and 119).

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
4

The flag for a transient field has been overloaded in the context of a method to mean that the method is a vararg method.

Likewise, the flag for a volatile field has been overloaded in the context of a method to mean that the method is a bridge method.

See: http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-Java5.pdf

pages 118-122 (or 26-30 in the PDF file)

Update

Reading the source code for Modifier.java confirms the first sentence of this answer ("The flag for a transient field has been overloaded"). Here's the relevant source code:

// Bits not (yet) exposed in the public API either because they
// have different meanings for fields and methods and there is no
// way to distinguish between the two in this class, or because
// they are not Java programming language keywords
static final int BRIDGE    = 0x00000040;
static final int VARARGS   = 0x00000080;
static final int SYNTHETIC = 0x00001000;
static final int ANNOTATION  = 0x00002000;
static final int ENUM      = 0x00004000;
static final int MANDATED  = 0x00008000;
Jason
  • 11,709
  • 9
  • 66
  • 82
Rob Heiser
  • 2,792
  • 1
  • 21
  • 28
  • 1
    This answer is the closest to the correct answer and should be the accepted answer. The link to ClassFileFormat is broken. – Jason Aug 02 '17 at 14:48