2763): at java.util.Timer$TimerImpl.run(Timer.java:284) 为什么会出现这个问题,这里有一篇大神的解答关于为什么不能再子线程中更新UI的讨论大神对代码的解读能力让人兴叹...AsyncTask ; 我用的是第一种方案: 把这个Runnable对象传给runOnUiThread(Runnable)。...这样Runnable对像就能在ui程序中被调用 public class MainActivity extends Activity { @Override protected void...timei; boolean net; private void networking(int i) { if (((int) SystemClock.uptimeMillis..., 0).show(); } } private void Netend(int i) { Toast.makeText(MainActivity.this
而强引用是造成Java内存泄漏的主要原因之一,内存空间不足时,Java虚拟机会抛出OutOfMemoryError ,使程序异常终止,但是注意,抛出错误也不会回收这些强引用的对象。...ThreadLocal有通过方法:调用get,set或remove方法时,就会尝试删除key为null的entry,可以释放value对象所占用的内存。...而强引用是造成Java内存泄漏的主要原因之一,内存空间不足时,Java虚拟机会抛出OutOfMemoryError ,使程序异常终止,但是注意,抛出错误也不会回收这些强引用的对象。...ThreadLocal有通过方法:调用get,set或remove方法时,就会尝试删除key为null的entry,可以释放value对象所占用的内存。...ThreadLocal有通过方法:调用get,set或remove方法时,就会尝试删除key为null的entry,可以释放value对象所占用的内存。
类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口 在加载阶段,虚拟机需要完成以下3件事情: 通过一个类的全限定名来获取定义此类的二进制字节流...二进制字节流就按照虚拟机所需的格式存储在方法区之中, 而且在Java堆中也创建一个java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据 加载时机 当应用程序启动的时候,所有的类不会被一次性加载...解析:虚拟机将常量池中的符号引用替换为直接引用(内存地址)的过程 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符.../float等),则为[I(int类型)、[F(float类型)等 3.常量在编译阶段会存入调用方法所在的类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化 /** *...调用任何现有对象的clone()方法; 通过java.io.ObjectInputStream类的getObject()方法反序列化。
之后可以通过调用Buffer.reset()方法恢复到这个position。方便数据的重新读取,而流只能是单向读取。...虚拟机会定期对垃圾内存进行回收,在某些特定的时间点,它会进行一次彻底的回收(full gc)。...但是调用System.gc()并不能够保证full gc马上就能被执行。所以在后面打代码中,会进行最多9次尝试,看是否有足够的可用堆外内存来分配堆外内存。...);)说到PhantomReference它其实主要是用来跟踪对象何时被回收的,它不能影响gc决策,但是gc过程中如果发现某个对象除了只有PhantomReference引用它之外,并没有其他的地方引用它了...} } public void clean() { //将当前Cleaner从Cleaner链表中移除,这样当clean()执行完后,Cleaner就是一个无引用指向的对象了,也就是可被
接下来我们就对实际开发中出现的这些内存问题,来进行优化。 JAVA 虚拟机 我们先来大概了解一下 Java 虚拟机里面运行时的数据区域有哪些。 ?..., stackoverflow 异常 本地方法栈 java 虚拟机规范中定义了 OutOfMemory ,stackoverflow 异常 注意 在 hotspotVM 中把虚拟机栈和本地方法栈合为了一个栈区...当这个方法运行完成后,就会退出方法栈,则引用对象的引用数为 0 ,这个对象会被回收。...注意: 软引用对象是在 jvm 内存不够的时候才会被回收,我们调用 System.gc() 方法只是起通知作用, JVM 什么时候扫描回收对象是 JVM 自己的状态决定的。...总结 引用类型 调用方式 GC 是否内存泄漏 强引用 直接调用 不回收 是 软引用 .get() 视内存情况回收 否 弱引用 .get() 回收 不可能 虚引用 null 任何时候都可能被回收,相当于没有引用一样
加载阶段完成后,虚拟机外部的 二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据。...· 对于引用数据类型reference来说,如数组引用、对象引用等,如果没有对其进行显式地赋值而直接使用,系统都会为其赋予默认的零值,即null。...我们可以理解为static final常量在编译期就将其结果放入了调用它的类的常量池中 – 解析:把类中的符号引用转换为直接引用 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口...、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。...并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 。
加载阶段完成后,虚拟机外部的 二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据。...我们可以理解为static final常量在编译期就将其结果放入了调用它的类的常量池中 解析:把类中的符号引用转换为直接引用 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口...、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。...– 创建类的实例,也就是new的方式 – 访问某个类或接口的静态变量,或者对该静态变量赋值 – 调用类的静态方法 – 反射(如Class.forName(“com.shengsiyuan.Test”)...并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 。
】 JNI实现源码分析【四 函数调用】 JNI实现源码分析【五 结束语】 正文 有了前面的铺垫,终于可以说说虚拟机是如何调用JNI方法的了。...在彻底弄懂dalvik字节码【一】中,我们跟踪过非Native方法的调用,现在我们来跟踪Native方法的调用,从dvmCallMethodV入手吧: 0x01:dvmCallMethodV void...(JNIEnv *env, jobject jthis, ...) {} 判断参数中是否存在引用类型的对象(非原型对象),如果有,将对象添加到局部引用表中获取其间接引用,替换参数。...调用dvmPlatformInvoke,最终就会调用到JNI方法了。dvmPlatformInvoke对不同的ABI有不同的实现。 从pResult中获取返回值,如果是间接引用,则转化为真实的对象。...同时,我们也看到了,在调用C函数前,真实的对象被转化为间接引用,然后传递到JNI方法中,同时,JNI方法返回的间接引用被转化为真实的对象,供下一步使用。
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据。...对于引用数据类型reference来说,如数组引用、对象引用等,如果没有对其进行显式地赋值而直接使用,系统都会为其赋予默认的零值,即null。...我们可以理解为static final常量在编译期就将其结果放入了调用它的类的常量池中 解析:把类中的符号引用转换为直接引用 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口...、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。...并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 。
,从字面知道,这里添加了一个GC的watcher,里面的线程运行条件是当虚拟机内存占用超过虚拟机分配的最大内存的3/4时,对一些Activity进行释放。...也就是说当执行到GC的时候,会调用到这里,然后执行Runnable的时候调用到虚拟机3/4内存的计算。 finallize方法最后重新创建了一个GcWatcher的弱引用。...sGcWatcher是一个静态对象,如果它是一个强引用,那么他就会存在静态引用方法区,就会导致这个强引用的GC线程无法回收。...所以作为弱引用,引用对象在被回收时就会触发sGcWatcher的finalize方法,执行结束时仔new一个弱引用出来,以保证下次的调用。 那么这里如何保证GC回收呢?...回到addGcWatcher,里面的线程运行条件是当虚拟机内存占用超过虚拟机分配的最大内存的3/4时,就会触发GC,对一些Activity进行释放。
思考这样一个问题,在编写代码时,使用引用,方法时,类知道这些引用方法的内存地址吗?显然是不知道的,因为类还未被加载到虚拟机中,你无法获得这些地址。...举例来说,对于一个方法的调用,编译器会生成一个包含目标方法所在的类、目标方法名、接收参数类型以及返回值类型的符号引用,来指代要调用的方法。 解析阶段的目的,就是将这些符号引用解析为实际引用。...虚拟机调用方法,进行类变量的初始化。...java类中对类变量进行初始化的两种方式: 在定义时初始化 在静态初始化块内初始化 3.1、方法相关 虚拟机会收集类及父类中的类变量及类方法组合为方法,根据定义的顺序进行初始化...; 如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口初始化; 使用反射API对某个类进行反射调用时,初始化这个类; Class.forName()会触发类的初始化
()方法是编译器收集代码中的静态变量(非final修饰)和静态代码块后生成的方法,它的主要作用是在类加载过程中的初始化阶段被调用,用于对静态变量进行赋值以及一些其他的初始化操作(这些操作可能写在静态代码块中...不同于类的构造方法,类的构造方法在字节码层面是()方法,()方法无需显式调用父类的()方法,虚拟机会保证在子类的()方法,父类的对类的主动引用,除此之外的场景,都不会去触发类的初始化,这些场景的行为称之为对类的被动引用。...去加载,也就是使用这个findBootstrapClassOrNull(name);方法去加载类,如果父类加载器加载失败,也就是加载的结果是class对象为null,那么将调用子类加载器的findClass...= NULL) return NULL; // 检查长度是否符合要求 const int str_len = (int)strlen(str); if (str_len > Symbol::
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个 java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据。...对于引用数据类型reference来说,如数组引用、对象引用等,如果没有对其进行显式地赋值而直接使用,系统都会为其赋予默认的零值,即null。...我们可以理解为static final常量在编译期就将其结果放入了调用它的类的常量池中 解析:把类中的符号引用转换为直接引用 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口...、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。...并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 。
本地方法就是java调用非java代码的接口,并不是所有的 JVM都支持本地方法, 因为 Java虚拟机规范上, 并没有明确要求本地方法的使用语言和具体实现方法....Java 虚拟机实现可以为程序员或用户提供对方法区域初始大小的控制,以及在方法区域大小可变的情况下,对最大和最小方法区域大小的控制。...,而是返回此时字符串常量池中对象的引用 jdk 1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份, 放入串池, 会把串池中的对象返回 String s1 = "...String s6 = s4.intern(); //尝试将s4在堆上的ab放入字符串常常量池中,但是此时字符串常常量池中存在,直接返回字符串常常量池中的对象引用(jdk 1.8)...线程来检测这些虚引用对象,当虚引用对象关联的实际对象被回收后,会调用虚引用对象的clean方法,然后调用任务对象的run方法 分配和回收原理 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用
然而,随着时间的推移,Hoare对自己当年引入空引用的决策进行了深刻的反思。在2009年,他坦言:“我将我之前发明的空引用的处理称为十亿美元的错误。...1965年,我在为一种面向对象的语言(ALGOL W)设计第一个全面的引用类型系统时,目标是确保所有引用的使用都应该是绝对安全的,由编译器自动进行检查。...它不仅改变了程序设计的方式,也引发了对异常处理、内存管理等众多领域的深入思考。三、空引用检查空引用识别我们先来想一个问题:虚拟机是如何识别到空引用的呢?...如果按照我们预想的对于每个对象引用做空是否为空的检查,那么对于每个列表对象都会做一次检查,这次检查会至少涉及到一条机器码比较指令。这个成本对于当下的Java应用程序来说是巨大且不可接受的。...检查细节下面代码是JDK8的虚拟机内部判别是否需要检查空引用的实现,调用链路依次如图中所示。
2.2. static 方法加锁 与实例方法不同,static 方法是无法获取到实例对象的 this 引用的,因此对 static 方法加锁,锁定的目标就是 class 对象,所有使用该类的线程都将获取到同一把锁...常用的使用方法有对 this 引用加锁和对 class 对象加锁: //this,当前实例对象锁 synchronized(this){ for(int j=0;j方法调用时,调用指令将会 检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有 monitor 对象,然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成...JVM 将 monitor 对象放在栈内存中,而不进行任何同步机制,从而保证了性能。 一旦出现获取轻量级锁失败,JVM 会尝试通过自旋的方式等待锁而不是让线程挂起。 5.3....需要注意的是,wait 方法调用后,线程将马上释放 monitor 锁,直到有线程调用 notify/notifyAll 方法后才能继续执行,而 sleep 方法只是让线程休眠一定时间,并不会释放锁。
虚拟机栈 作用:存储线程中Java方法调用的状态,包括局部变量、参数、返回值以及运算的中间结果等。一个Java虚拟机栈包含了多个栈帧,一个栈帧用来存储:局部变量表、操作数栈、动态链接、方法出口等信息。...当线程调用一个Java方法时,虚拟机压入一个新的栈帧到该线程的Java虚拟机栈中,在该方法执行完成后,这个栈帧就从Java虚拟机栈中弹出。我们平常所说的栈内存(Stack)指的就是Java虚拟机栈。...关于对垃圾进行回收,被引用的对象是存活的对象,而不被引用的对象是死亡的对象(也就是垃圾),GC要区分出存活的对象和死亡的对象(也就是垃圾标记),并对垃圾进行回收。...对程序需要不被长时间打断的实时环境比较有利。 缺点: 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。...在Java中,可以作为GC Roots的对象主要有以下几种: 虚拟机栈(本地变量表)中正在运行使用的引用 本地方法栈中JNI引用的对象。 方法区中运行时常量池引用的对象。
2、构造对象。 3、从超类到子类对static成员进行初始化,类的static成员的初始化在ClassLoader加载该类时进行。 4、超类成员变量按顺序初始化,递归调用超类的构造方法。...5、子类成员变量按顺序初始化,一旦对象被创建,子类构造方法就调用该对象并为某些变量赋值。 2、InUse(应用) 此时对象至少被一个强引用持有。...1、资源性对象未关闭 对于资源性对象不再使用时,应该立即调用它的close()函数,将其关闭,然后再置为null。...此外,还有entryRemoved方法,当一个缓存对象被丢弃时调用的方法,当第一个参数为true:表明缓存对象是为了腾出空间而被清理。...所以这些方法都是在ImageLoader中的doInBackground方法中调用,代码如下所示: @Override protected Bitmap doInBackground(Void... params
软引用 这种引用的功能即是前言部分提到的:如果某个 Java 对象只被软引用所指向,那么在 JVM 要新建一个对象的时候,如果当前虚拟机所剩下的堆内存不足以保存这个要新建的对象的时候(即虚拟机将要抛出...也不能通过虚引用来得到其指向的对象(其 get 方法直接返回 null)。那么虚引用有什么作用呢?虚引用一般会配合 引用队列(ReferenceQueue)来使用。...下面来看看对弱引用的测试,我们改一下 main 方法中的一行代码:test.testWeakReference(); ?...GC 调用, * 之后,通过该引用对象的 get 方法得到的返回值为 null, 该方法不应该被程序员主动调用 */ public void clear() {...ReferenceQueue.NULL : queue; } } 我们在 Reference 类中的 enqueue 方法(这个方法本身会被 GC 线程调用)中发现其直接调用了对应引用队列(ReferenceQueue
领取专属 10元无门槛券
手把手带您无忧上云