java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

大家好,又见面了,我是你们的朋友全栈君。

内存分配机制

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

逐步分析

类加载检查:

虚拟机遇到一条new指令(new关键字、对象的克隆、对象的序列化等)时,会先去检查这个指令的参数在常量池中定位到一个类的符号引用,并且这个符号引用代表的类是否应被加载过,如果没有那么就去加载该类

立即学习“Java免费学习笔记(深入)”;

分配内存

类加载完毕后会给对象分配内存空间。对象的所需的内存大小在类加载完毕后就便可完全确认,为对象分配内存大小的空间等同于把一块确定大小的内存从java堆中划分出来。

如何划分内存?

指针碰撞(默认使用指针碰撞):如果java堆内存是绝对规整的,那么会把所有用过的内存放在一边,空闲的内存放在另外一边,中间用一个指针来作为分界点的指示器,那所分配的内存仅仅把那个指针空闲空间的挪动一段与对象大小相同的距离。

空闲列表:如果java堆内存不是绝对规整的,已使用的空间和未使用的空间互相交错,那么虚拟机维护一份列表,记录哪些内存块是可用的,在划分内存空间的时候从列表中找到一块足够大的内存空间分配给对象实例,并更新列表上的记录。

分配内存遇到高并发的问题?现在有多个线程同时并发需要进行内存分配

CAS :虚拟机采用失败重试的机制方式保证操作的原子性对分配内存空间的动作进行同步处理,第一个线程抢占到了分配空间,第二个线程没有抢占到就重试抢占后面一块内存空间

本地线程分配缓冲:把内存分配的动作按照线程分配在不同的空间之中完成,也就是每个线程在java堆中预先分配出一块小的内存。通过-XX:+/-UseTLAB参数来设定虚拟机是否使用(JVM默认开启-XX:+UseTLAB) ,-XX:TLABSize指定TLAB大小,默认是Eden区的百分之1,放不下就走CAS

初始化

内存分配完毕后,给变量赋默认值,如果使用了TLAB,那么这个过程也可以提前至TLAB分配时进行

4.设置对象头

初始化零值之后,虚拟机要对对象进行必要的设置,例如这个对象是那个类的实例,如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息都存放在对象的对象头Object Header中。

在HosSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头,实例数据,对齐填充。

1.HotSpot虚拟机的对象头包括三部分信息:Mark Word、Klass Pointer类型指针、数组长度

Mark Word标记字段(32位 4字节 ,64位占8字节)用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。

对象头的另外一部分是类型指针(Klass Point 开启压缩占4字节,关闭压缩占8字节),并不是Class ,我们使用的对象的getClass方法的那个Class对象是在堆内存而这个是类的元数据信息 。即对象指向它类的元数据的指针,元数据信息是放在方法区之中,虚拟机通过这个指针来确定这个对象是那个类的实例,类的元数据信息是放在C++的对象来承载的

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

实例数据

对象的实例数据就是该对象的引用大小

对齐填充

保证对象是8个字节的整数倍。64位的机器每一行都是64位,如果现在8个字节直接取一行,那如果不是对齐,还要评估这个对象的大小,还要从这个对象大小的起始位置开始偏移,这样非常的麻烦,8个字节对齐是最优的寻址方式.

什么是java对象的 指针压缩?

jdk1.6 update14开始,在64bit操作系统中,JVM支持指针压缩

jvm配置参数:启用指针压缩:­XX:+UseCompressedOops(默认开启),禁止指针压缩:­XX:­UseCompressedOops

为什么要进行指针压缩?

1.在64位平台的HotSpot中使用32位指针,内存使用会出多1.5倍左右,同时GC也会承受较大压力

2.在jvm中,32位地址最大支持4G内存(2的32次方),可以通过对象指针存入堆内存时压缩的编码然后在取出到CPU寄存器后解码进行优化(对象指针在堆内存中是32位,在寄存器是35位,2的35次是32G),使得JVM使用32位地址就可以支持更大的内存配置

如果压缩了用4个字节没有压缩用8个字节,节约内存空间。多一个Object header,实际没开指针压缩是通过两块一起来存储Klass Point,成员对象String类型也用8个字节来存储 ,成员对象Object也需要8个字节 。那么我们每个对象都有对象头,指针压缩可以减少我们每个对象的大小,同样的内存大小可以放更多的对象才会触发GC

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…
java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

执行方法

成员变量的赋值以及构造方法的调用

对象内存分配

对象内存分配流程图

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

对象栈上分配

JVM内存分配可以知道JAVA中的对象都是堆上进行分配,当对象没有被引用的时候,需要一开GC进行回收内存,如果对象数量较多的时候,会给GC带来较大的压力,也间接影响了应用的性能。为了减少临时对象在堆内分配的数量,JVM通过逃逸分析来确定该对象不会被外部访问。如果不会逃逸可以将该对象在栈上分配内存,这样对象所占用的内存空间就可以随着栈帧出栈而销毁,就减轻了垃圾回收的压力。

对象逃逸分析:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中

public class AllotOnStack {

/**

* Description : 栈上分配,标量替换

* 代码调用了1亿次alloc(),如果是分配到堆上,大概需要1GB以上堆空间,如果堆空间小于该值,必然会触发GC。

* 使用如下参数不会发生GC

* -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:+EliminateAllocations

* 使用如下参数都会发生大量GC

* -Xmx15m -Xms15m -XX:-DoEscapeAnalysis -XX:+PrintGC -XX:+EliminateAllocations

* -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-EliminateAllocations

**/

public static void main(String[] args) {

long start = System.currentTimeMillis();

System.out.println(start);

for (int i = 0; i

allot();

}

long end = System.currentTimeMillis();

System.out.println(end);

System.out.println(end – start);

}

private static void allot() {

AllotOnBO allotOnBO = new AllotOnBO();

allotOnBO.setA(“123”);

}

}

class AllotOnBO {

public void setA(String a) {

this.a = a;

}

private String a;

}

很显然test1方法中的user对象被返回了,这个对象的作用域范围不确定,test2方法中的user对象我们可以确定当方法结 束这个对象就可以认为是无效对象了,对于这样的对象我们其实可以将其分配在栈内存里,让其在方法结束时跟随栈内 存一起被回收掉。

JVM对于这种情况可以通过开启逃逸分析参数(-XX:+DoEscapeAnalysis)来优化对象内存分配位置,使其通过标量替换优 先分配在栈上(栈帧上分配),JDK7之后默认开启逃逸分析,如果要关闭使用参数(-XX:-DoEscapeAnalysis)

标量替换:通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而是将该 对象成员变量分解若干个被这个方法使用的成员变量所代替,这些代替的成员变量在栈帧或寄存器上分配空间,这样就 不会因为没有一大块连续空间导致对象内存不够分配。开启标量替换参数(-XX:+EliminateAllocations),JDK7之后默认 开启。

标量与聚合量:标量即不可被进一步分解的量,而JAVA的基本数据类型就是标量(比如:int,long等基本数据类型以及reference类型等),标量的对立就是可以被进一步分解的量,也就是聚合量。而JAVA中的对象就是可以被进一步分解的聚合量。

结论:栈上分配的依赖于逃逸分析和标量替换,如果不开变量替换意义不大

Minor GC 和Full GC 有什么区别

MinorGC / Young GC:指的是新生代的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。

MajorGC / Full GC:一般指老年代,年轻代,方法区的垃圾回收,Major GC 的速度一遍比 Minor GC的慢10倍以上

Eden与Survivor区默认8:1

大量的对象被分配在Eden区,Eden区满了之后出发minor GC ,可能百分之99的对象都被当成垃圾回收掉,存活(标记)对象会被移动到Survivor,下一次当Eden区又满了之后会触发Minor GC把Eden区和Survivor区的存活对象移动到另一块Survivor区.每移动一次年龄加1,一直达到年龄15的时候会把移动到老年代。新生代的对象都是朝生夕死的,所以为了减少Minor GC的频率 尽量让Eden区尽量大 ,Survivor区够用即可。JVM默认比例已经很合适了

JVM默认有这个参数-XX:+UseAdaptiveSizePolicy(默认开启),会导致这个8:1:1比例自动变化,如果不想这个比例有变化可以设置参数-XX:-UseAdaptiveSizePolicy

public class MinorGc {

// -XX:+PrintGCDetails

public static void main(String[] args) {

byte[] allocation1, allocation2;

allocation1 = new byte[60000 * 1024];

allocation2 = new byte[20000 * 1024];

}

}

[GC (Allocation Failure) [PSYoungGen: 65245K->776K(76288K)] 65245K->60784K(251392K), 0.0333426 secs] [Times: user=0.05 sys=0.03, real=0.05 secs]

Heap

PSYoungGen total 76288K, used 21431K [0x000000076b400000, 0x0000000774900000, 0x00000007c0000000)

eden space 65536K, 31% used [0x000000076b400000,0x000000076c82bef8,0x000000076f400000)

from space 10752K, 7% used [0x000000076f400000,0x000000076f4c2020,0x000000076fe80000)

to space 10752K, 0% used [0x0000000773e80000,0x0000000773e80000,0x0000000774900000)

ParOldGen total 175104K, used 60008K [0x00000006c1c00000, 0x00000006cc700000, 0x000000076b400000)

object space 175104K, 34% used [0x00000006c1c00000,0x00000006c569a010,0x00000006cc700000)

Metaspace used 3487K, capacity 4498K, committed 4864K, reserved 1056768K

class space used 387K, capacity 390K, committed 512K, reserved 1048576K

分配了allocation1对象 这个时候Eden区几乎已经满了,下一步指令又要分配20M对象 ,Eden区已经不够给allocation2 分配内存空间了虚拟机触发Minor GC ,GC期间虚拟机发现结果From区只有10M放不下 ,所以只好把新生代对象提前存放到老年代,老年代的空间足够存放allocation1,剩下的对象JVM自身的一些类 比如:Object,加载器被移动到了From区。Minor GC完之后Eden区给 allocation2 对象分配内存

大对象直接进入老年代

大对象就是需要大量连续空间内存空间的对象比如:字符串,数组。JVM参数-XX:PretenureSizeThreshold可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在Serial和ParNew两个收集器下有效

比如设置JVM参数-XX:+PrintGCDetails -XX:PretenureSizeThreshold=1000000(字节) -XX:+UseSerialGC ,在执行刚刚的代码这个时候发现大对象直接进入老年代

为什么这样设计?

为了避免为大对象分配内存时的复制操作而降低效率

Heap

def new generation total 78656K, used 6995K [0x00000006c1c00000, 0x00000006c7150000, 0x0000000716800000)

eden space 69952K, 10% used [0x00000006c1c00000, 0x00000006c22d4ed0, 0x00000006c6050000)

from space 8704K, 0% used [0x00000006c6050000, 0x00000006c6050000, 0x00000006c68d0000)

to space 8704K, 0% used [0x00000006c68d0000, 0x00000006c68d0000, 0x00000006c7150000)

tenured generation total 174784K, used 80000K [0x0000000716800000, 0x00000007212b0000, 0x00000007c0000000)

the space 174784K, 45% used [0x0000000716800000, 0x000000071b620020, 0x000000071b620200, 0x00000007212b0000)

Metaspace used 3485K, capacity 4498K, committed 4864K, reserved 1056768K

class space used 387K, capacity 390K, committed 512K, reserved 1048576K

长期存活的对象将进入老年代

JVM采用了分代年龄收集的思想,那么回收这个对象的时候就需要考虑放在Survivor还是老年代,考虑的依据虚拟机会为每个对象分配一个年龄计算器,如果对象在Eden区经过一次Monir GC后存活下的对象,移动到Survivor后年龄+1,之后的Minor GC每存活一次年龄再次+1 一直加到15(CMS默认是6,不同的垃圾收集器略不同),就会被移动到老年代。可以通过参数-XX:MaxTenuringThreshold来设置

对象动态年龄判断

如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。那么年龄大于或等于这批的对象将直接挪到老年代,例如:年龄1+年龄2+年龄3+年龄4+年龄N的对象 其中年龄1,2,3的对象总和超过了Survivor区域的百分之50(-XX:TargetSurvivorRatio可以指定),那么就会将3和3以上的对象都进入老年代。

老年代分配担保机制(触发Full GC)

年轻代每次Minor GC之前JVM都会计算下老年代剩余可用空间,如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象)就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了

如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次Minor GC后进入老年代的对象的平均大小。

如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full GC ,对老年代和年轻代一起回收一次垃圾,如果回收完还是没有足够空间存放新的对象就会发生OOM

当然,如果Minor GC之后剩余存活的需要挪到老年代的对象还是大于老年代可用空间,那么也会触发Full GC ,Full GC完之后如果还是没有空间放Minor GC之后的存活对象,则会发生OOM

老年代分配担保机制担保的就是存在Full GC的情况下 减少一次Minor GC ,如果没有担保那么就是Minor GC->Full GC

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

对象内存回收

引用计数器

给对象中添加一个引用计数器,每当一个地方引用它,计数器就加;当引用失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。

这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最重要原因它很难解决对象之间互相循环引用的问题。所谓对象之间的互相引用问题,如下面代码所示:除了对象ObjA和ObjB互相引用着对方之外,这两个对象之间再无任何引用。但是因为他们互相引用对方,导致他们的引用计数器都不为0,于是引用计数算法无法通知GC回收他们

public class ReferenceCountingGc {

Object instance = null;

public static void main(String[] args) {

ReferenceCountingGc objA = new ReferenceCountingGc();

ReferenceCountingGc objB = new ReferenceCountingGc();

objA.instance = objB;

objB.instance = objA;

objA = null;

objB = null;

}

}

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

可达性分析算法

将GCRoots对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象标记为非垃圾对象,其余未标记的对象都是垃圾对象

GC Roots根节点: 线程栈的本地变量,静态变量,本地方法栈的变量等等

java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…

finalize()方法最终判断对象是否存活

即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这个时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历再次标记过程

标记的前提是对象在进行可达性分析法后发现没有与GC Roots相连接的引用链

1.第一次标记并进行一次筛选

筛选的条件就是该对象是否覆盖了finalize()方法,没有覆盖直接回收

2.第二次标记

如果这个对象覆盖了finalize()方法,只要重新与引用链上任何一个对象关联即可,比如把自己赋值给某个类的变量或对象的成员变量,那么第二次标记的时候它将移除“即将回收”的集合。

注意:一个对象的finalize()方法只会被执行一次,也就是说通过调用finalize方法自我救命的机会就一次

如何判断一个类是无用的类?

方法区主要回收的是无用的类,如何判断一个类是无用的类

类需要满足下面三个条件才能算是无用的类

该类的所有实例都被回收,Java堆中没有存在该类是任何实例

加载该类的ClassLoader被回收(只有自定义的类加载器才能被回收)

该类的对应的Java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

最后

希望我总结的这些东西对你们会有帮助。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/146604.html原文链接:https://javaforall.cn

以上就是java栈内存初始化,阿里面试官:小伙子,你给我说一下JVM对象创建与内存分配机制吧…的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/21302.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月1日 12:13:09
下一篇 2025年11月1日 12:19:03

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 em 和 transition 设置后元素没有放大?

    元素设置 em 和 transition 后不放大 一个 youtube 视频中展示了设置 em 和 transition 的元素在页面加载后会放大,但同样的代码在提问者电脑上没有达到预期效果。 可能原因: 问题在于 css 代码的位置。在视频中,css 被放置在单独的文件中并通过 link 标签引…

    2025年12月24日
    100
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000

发表回复

登录后才能评论
关注微信