private Object readObject0(boolean unshared) throws IOException { boolean oldMode = bin.getBlockDataMode(); if (oldMode) { int remain = bin.currentBlockRemaining(); if (remain > 0) { throw new OptionalDataException(remain); } else if (defaultDataEnd) { /* * Fix for 4360508: stream is currently at the end of a field * value block written via default serialization; since there * is no terminating TC_ENDBLOCKDATA tag, simulate * end-of-custom-data behavior explicitly. */ throw new OptionalDataException(true); } bin.setBlockDataMode(false); }
case TC_CLASSDESC: case TC_PROXYCLASSDESC: return readClassDesc(unshared);
case TC_STRING: case TC_LONGSTRING: return checkResolve(readString(unshared));
case TC_ARRAY: return checkResolve(readArray(unshared));
case TC_ENUM: return checkResolve(readEnum(unshared));
case TC_OBJECT: return checkResolve(readOrdinaryObject(unshared));
case TC_EXCEPTION: IOException ex = readFatalException(); throw new WriteAbortedException("writing aborted", ex);
case TC_BLOCKDATA: case TC_BLOCKDATALONG: if (oldMode) { bin.setBlockDataMode(true); bin.peek(); // force header read throw new OptionalDataException( bin.currentBlockRemaining()); } else { throw new StreamCorruptedException( "unexpected block data"); }
case TC_ENDBLOCKDATA: if (oldMode) { throw new OptionalDataException(true); } else { throw new StreamCorruptedException( "unexpected end of block data"); }
default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } } finally { depth--; bin.setBlockDataMode(oldMode); } }
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { /** Cache of unfinished FactoryBean instances: FactoryBean name --> BeanWrapper */ private final Map<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>(16); }
Thread t1 = new Thread(new ExectorThread()); Thread t2 = new Thread(new ExectorThread()); t1.start(); t2.start(); System.out.println("end"); }
运行结果:
在主线程 main 中无论调用多少次,获取到的实例都是同一个,都在两个子线程中分别获取到了不同的实例。那么ThreadLocal是如果实现这样的效果的呢?我们知道上面的单例模式为了达到线程安全的目的,给方法上锁,以时间换空间。 ThreadLocal将所有的对象全部放在ThreadLocalMap中,为每个线程都提供一个对象,实际上是以空间换时间来实现线程间隔离的。
private static Calendar createCalendar(TimeZone zone, Locale aLocale) { CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale) .getCalendarProvider(); if (provider != null) { try { return provider.getInstance(zone, aLocale); } catch (IllegalArgumentException iae) { // fall back to the default instantiation } }
Calendar cal = null;
if (aLocale.hasExtensions()) { String caltype = aLocale.getUnicodeLocaleType("ca"); if (caltype != null) { switch (caltype) { case "buddhist": cal = new BuddhistCalendar(zone, aLocale); break; case "japanese": cal = new JapaneseImperialCalendar(zone, aLocale); break; case "gregory": cal = new GregorianCalendar(zone, aLocale); break; } } } if (cal == null) { // If no known calendar type is explicitly specified, // perform the traditional way to create a Calendar: // create a BuddhistCalendar for th_TH locale, // a JapaneseImperialCalendar for ja_JP_JP locale, or // a GregorianCalendar for any other locales. // NOTE: The language, country and variant strings are interned. if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") { cal = new BuddhistCalendar(zone, aLocale); } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" && aLocale.getCountry() == "JP") { cal = new JapaneseImperialCalendar(zone, aLocale); } else { cal = new GregorianCalendar(zone, aLocale); } } return cal; }
public interface Quadrangle { long getWidth(); long getHeight(); }
修改长方形 Rectangle 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public class Rectangle implements Quadrangle {
private long height; private long width; @Override public long getWidth() { return width; } public long getHeight() { return height; } public void setHeight(long height) { this.height = height; } public void setWidth(long width) { this.width = width; } }
修改正方形类 Square 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public class Square implements Quadrangle {
private long length; public long getLength() { return length; } public void setLength(long length) { this.length = length; } @Override public long getWidth() { return length; } @Override public long getHeight() { return length; } }
public class Pojo { public int a; public String b; public int c; public boolean d; private long e; // e设置为私有的,后面讲解为什么 public Object f; Pojo() { e = 1024L;}
public static void main(String[] args) { Pojo pojo = new Pojo(); System.out.println(ClassLayout.parseInstance(pojo).toPrintable()); } }
[root@iz2zea13o0oyywo7z5hawlz ~]# vmstat procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 109592 141200 1445092 0 0 0 3 12 22 0 0 99 0 0
public class Person { private String name = "Kevin"; private int age; private final double salary = 100; private static String address; private final static String hobby = "Programming"; public void say() { System.out.println("person say..."); } public static int calc(int op1,int op2) { op1 = 3; int result = op1 + op2; return result; } public static void order() {
Compiled from "Person.java" public class Person { ... public static int calc(int, int); Code: 0: iconst_3 //将int类型常量3压入[操作数栈] 1: istore_0 //将int类型值存入[局部变量0] 2: iload_0 //从[局部变量0]中装载int类型值入栈 3: iload_1 //从[局部变量1]中装载int类型值入栈 4: iadd //将栈顶元素弹出栈,执行int类型的加法,结果入栈 【For example, the iadd instruction (§iadd) adds two int values together. It requires that the int values to be added be the top two values of the operand stack, pushed there by previous instructions. Both of the int values are popped from the operand stack. They are added, and their sum is pushed back onto the operand stack. Subcomputations may be nested on the operand stack, resulting in values that can be used by the encompassing computation.】 5: istore_2 //将栈顶int类型值保存到[局部变量2]中 6: iload_2 //从[局部变量2]中装载int类型值入栈 7: ireturn //从方法中返回int类型的数据 ... }
例子中的Java虚拟机和栈帧,如图:
1.2 栈指向堆
如果在栈帧中有一个变量,类型为引用类型,比如Object obj = new Object(),这个时候就是典型的栈中的元素指向堆中的对象。
例如:有对象A、B、C等创建在Eden区,但是由于Eden区的内存空间有限,其大小只有100M,假如意见使用了100M或达到了一个设定的临界值,这个时候就需要对Eden区的内存空间进行清理,即垃圾回收(Garbage Collect),这样的GC也被称为Minor GC, Minor GC指的是Young区的GC。
com.gooagoo.dop.trans.test.json.HeapOut Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at com.gooagoo.dop.trans.test.json.HeapOut.main(HeapOut.java:12)
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.lang.ClassLoader.defineClass(ClassLoader.java:642) at com.gooagoo.dop.trans.test.json.MyMetaspace.createClasses(MyMetaspace.java:21) at com.gooagoo.dop.trans.test.json.MyMetaspace.main(MyMetaspace.java:30)
3.4 虚拟机栈StackOvewFlow
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12
public class JvmStack {
public static long count = 0; public static void method(long i) { System.out.println(count++); method(i); }
public static void main(String[] args) { method(1); } }
public class Student{ private String name; private int age; private static String sex; public void say(){ System.out.println("student say..."); } public int calcStudents(int op1,int op2){ return op1 + op2; } }
The magic item supplies the magic number identifying the class file format; it has the value 0xCAFEBABE.
1
cafe babe
minor_version, major_version
1
0000 0031
31对应10进制的49,代表JDK 8中的一个版本
constant_pool_count
1
0028
对应十进制28,代表常量池中28个常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }
The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits. Other data areas are per thread. Per-thread data areas are created when a thread is created and destroyed when the thread exits.
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.
The Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own pc (program counter) register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method (§2.6) for that thread. If that method is not native, the pc register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java Virtual Machine's pc register is undefined. The Java Virtual Machine's pc register is wide enough to hold a returnAddress or a native pointer on the specific platform.